Merge "Do not use hidden API ParcelableException"
diff --git a/.mailmap b/.mailmap
index b061ccf..40c295e 100644
--- a/.mailmap
+++ b/.mailmap
@@ -1 +1 @@
-Ember Rose <emberr@google.com> <ashleyrose@google.com>
+Ember Rose <emberrose@google.com> <ashleyrose@google.com>
diff --git a/Android.bp b/Android.bp
index 594126f..e2a4219 100644
--- a/Android.bp
+++ b/Android.bp
@@ -170,6 +170,15 @@
 }
 
 filegroup {
+    name: "framework-mms-sources",
+    srcs: [
+        "mms/java/**/*.java",
+        "mms/java/**/*.aidl",
+    ],
+    path: "mms/java",
+}
+
+filegroup {
     name: "framework-wifi-sources",
     srcs: [
         "wifi/java/**/*.java",
@@ -193,6 +202,7 @@
         ":framework-mca-filterfw-sources",
         ":framework-mca-filterpacks-sources",
         ":framework-mime-sources",
+        ":framework-mms-sources",
         ":framework-opengl-sources",
         ":framework-rs-sources",
         ":framework-sax-sources",
@@ -252,6 +262,7 @@
             "media/mca/effect/java",
             "media/mca/filterfw/java",
             "media/mca/filterpacks/java",
+            "mms/java",
             "opengl/java",
             "rs/java",
             "sax/java",
@@ -402,6 +413,7 @@
         "framework-platform-compat-config",
         "libcore-platform-compat-config",
         "services-platform-compat-config",
+        "media-provider-platform-compat-config",
     ],
     sdk_version: "core_platform",
 }
@@ -415,7 +427,7 @@
 
 java_library {
     name: "framework-annotation-proc",
-    defaults: ["framework-defaults"],
+    defaults: ["framework-aidl-export-defaults"],
     srcs: [":framework-all-sources"],
     installable: false,
     plugins: [
@@ -441,7 +453,9 @@
     srcs: [
         "core/java/android/annotation/IntDef.java",
         "core/java/android/annotation/UnsupportedAppUsage.java",
-        ":unsupportedappusage_annotation_files",
+    ],
+    static_libs: [
+        "art.module.api.annotations",
     ],
 
     sdk_version: "core_current",
@@ -820,6 +834,7 @@
     "media/mca/filterfw/java",
     "media/mca/filterpacks/java",
     "drm/java",
+    "mms/java",
     "opengl/java",
     "sax/java",
     "telecomm/java",
@@ -941,6 +956,7 @@
         "test-base/src/**/*.java",
         ":opt-telephony-srcs",
         ":opt-net-voip-srcs",
+        ":core-current-stubs-source",
         ":core_public_api_files",
         ":updatable-media-srcs",
         "test-mock/src/**/*.java",
@@ -1005,6 +1021,7 @@
         "core/java/**/*.logtags",
         ":opt-telephony-srcs",
         ":opt-net-voip-srcs",
+        ":core-current-stubs-source",
         ":core_public_api_files",
         ":updatable-media-srcs",
         ":jobscheduler-framework-source",
@@ -1558,3 +1575,14 @@
     ],
 }
 
+// Avoid including Parcelable classes as we don't want to have two copies of
+// Parcelable cross the process.
+filegroup {
+    name: "framework-cellbroadcast-shared-srcs",
+    srcs: [
+        "core/java/android/util/LocalLog.java",
+        "core/java/android/util/Slog.java",
+        "core/java/com/android/internal/util/State.java",
+        "core/java/com/android/internal/util/StateMachine.java",
+    ],
+}
\ No newline at end of file
diff --git a/apct-tests/perftests/core/Android.mk b/apct-tests/perftests/core/Android.mk
index 3f87a1c..968478c 100644
--- a/apct-tests/perftests/core/Android.mk
+++ b/apct-tests/perftests/core/Android.mk
@@ -9,8 +9,11 @@
   src/android/os/ISomeService.aidl
 
 LOCAL_STATIC_JAVA_LIBRARIES := \
+    androidx.appcompat_appcompat \
     androidx.test.rules \
     androidx.annotation_annotation \
+    apct-perftests-overlay-apps \
+    apct-perftests-resources-manager-apps \
     apct-perftests-utils \
     guava
 
@@ -25,5 +28,6 @@
 LOCAL_ASSET_DIR := $(TOP)/external/google-fonts/dancing-script
 
 LOCAL_COMPATIBILITY_SUITE += device-tests
+LOCAL_CERTIFICATE := platform
 
-include $(BUILD_PACKAGE)
+include $(BUILD_PACKAGE)
\ No newline at end of file
diff --git a/apct-tests/perftests/core/AndroidManifest.xml b/apct-tests/perftests/core/AndroidManifest.xml
index a564a4d..525975d 100644
--- a/apct-tests/perftests/core/AndroidManifest.xml
+++ b/apct-tests/perftests/core/AndroidManifest.xml
@@ -5,8 +5,11 @@
     <permission android:name="com.android.perftests.core.TestPermission" />
     <uses-permission android:name="com.android.perftests.core.TestPermission" />
 
-    <uses-permission
-        android:name="android.permission.GET_ACCOUNTS" />
+    <uses-permission android:name="android.permission.CHANGE_OVERLAY_PACKAGES" />
+    <uses-permission android:name="android.permission.DELETE_PACKAGES" />
+    <uses-permission android:name="android.permission.GET_ACCOUNTS" />
+    <uses-permission android:name="android.permission.INSTALL_PACKAGES"/>
+    <uses-permission android:name="android.permission.INTERACT_ACROSS_USERS" />
 
     <application>
         <uses-library android:name="android.test.runner" />
diff --git a/apct-tests/perftests/core/apps/overlay/Android.bp b/apct-tests/perftests/core/apps/overlay/Android.bp
new file mode 100644
index 0000000..7bee30e
--- /dev/null
+++ b/apct-tests/perftests/core/apps/overlay/Android.bp
@@ -0,0 +1,188 @@
+// 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_test_helper_app {
+    name: "Overlay0",
+    aaptflags: [
+        "--rename-manifest-package com.android.perftests.overlay0",
+    ]
+}
+
+android_test_helper_app {
+    name: "Overlay1",
+    aaptflags: [
+        "--rename-manifest-package com.android.perftests.overlay1",
+    ]
+}
+
+android_test_helper_app {
+    name: "Overlay2",
+    aaptflags: [
+        "--rename-manifest-package com.android.perftests.overlay2",
+    ]
+}
+
+android_test_helper_app {
+    name: "Overlay3",
+    aaptflags: [
+        "--rename-manifest-package com.android.perftests.overlay3",
+    ]
+}
+
+android_test_helper_app {
+    name: "Overlay4",
+    aaptflags: [
+        "--rename-manifest-package com.android.perftests.overlay4",
+    ]
+}
+
+android_test_helper_app {
+    name: "Overlay5",
+    aaptflags: [
+        "--rename-manifest-package com.android.perftests.overlay5",
+    ]
+}
+
+android_test_helper_app {
+    name: "Overlay6",
+    aaptflags: [
+        "--rename-manifest-package com.android.perftests.overlay6",
+    ]
+}
+
+android_test_helper_app {
+    name: "Overlay7",
+    aaptflags: [
+        "--rename-manifest-package com.android.perftests.overlay7",
+    ]
+}
+android_test_helper_app {
+    name: "Overlay8",
+    aaptflags: [
+        "--rename-manifest-package com.android.perftests.overlay8",
+    ]
+}
+
+android_test_helper_app {
+    name: "Overlay9",
+    aaptflags: [
+        "--rename-manifest-package com.android.perftests.overlay9",
+    ]
+}
+
+android_test_helper_app {
+    name: "LargeOverlay0",
+    resource_dirs : [ "res_large" ],
+    aaptflags: [
+        "--rename-manifest-package com.android.perftests.overlay.large0",
+    ]
+}
+
+android_test_helper_app {
+    name: "LargeOverlay1",
+    resource_dirs : [ "res_large" ],
+    aaptflags: [
+        "--rename-manifest-package com.android.perftests.overlay.large1",
+    ]
+}
+
+android_test_helper_app {
+    name: "LargeOverlay2",
+    resource_dirs : [ "res_large" ],
+    aaptflags: [
+        "--rename-manifest-package com.android.perftests.overlay.large2",
+    ]
+}
+
+android_test_helper_app {
+    name: "LargeOverlay3",
+    resource_dirs : [ "res_large" ],
+    aaptflags: [
+        "--rename-manifest-package com.android.perftests.overlay.large3",
+    ]
+}
+
+android_test_helper_app {
+    name: "LargeOverlay4",
+    resource_dirs : [ "res_large" ],
+    aaptflags: [
+        "--rename-manifest-package com.android.perftests.overlay.large4",
+    ]
+}
+
+android_test_helper_app {
+    name: "LargeOverlay5",
+    resource_dirs : [ "res_large" ],
+    aaptflags: [
+        "--rename-manifest-package com.android.perftests.overlay.large5",
+    ]
+}
+
+android_test_helper_app {
+    name: "LargeOverlay6",
+    resource_dirs : [ "res_large" ],
+    aaptflags: [
+        "--rename-manifest-package com.android.perftests.overlay.large6",
+    ]
+}
+
+android_test_helper_app {
+    name: "LargeOverlay7",
+    resource_dirs : [ "res_large" ],
+    aaptflags: [
+        "--rename-manifest-package com.android.perftests.overlay.large7",
+    ]
+}
+
+android_test_helper_app {
+    name: "LargeOverlay8",
+    resource_dirs : [ "res_large" ],
+    aaptflags: [
+        "--rename-manifest-package com.android.perftests.overlay.large8",
+    ]
+}
+
+android_test_helper_app {
+    name: "LargeOverlay9",
+    resource_dirs : [ "res_large" ],
+    aaptflags: [
+        "--rename-manifest-package com.android.perftests.overlay.large9",
+    ]
+}
+
+java_library {
+    name: "apct-perftests-overlay-apps",
+    java_resources: [
+        ":Overlay0",
+        ":Overlay1",
+        ":Overlay2",
+        ":Overlay3",
+        ":Overlay4",
+        ":Overlay5",
+        ":Overlay6",
+        ":Overlay7",
+        ":Overlay8",
+        ":Overlay9",
+        ":LargeOverlay0",
+        ":LargeOverlay1",
+        ":LargeOverlay2",
+        ":LargeOverlay3",
+        ":LargeOverlay4",
+        ":LargeOverlay5",
+        ":LargeOverlay6",
+        ":LargeOverlay7",
+        ":LargeOverlay8",
+        ":LargeOverlay9",
+    ],
+}
\ No newline at end of file
diff --git a/apct-tests/perftests/core/apps/overlay/AndroidManifest.xml b/apct-tests/perftests/core/apps/overlay/AndroidManifest.xml
new file mode 100644
index 0000000..52f5a89
--- /dev/null
+++ b/apct-tests/perftests/core/apps/overlay/AndroidManifest.xml
@@ -0,0 +1,21 @@
+<?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 xmlns:android="http://schemas.android.com/apk/res/android"
+          package="com.android.perftests.overlay">
+    <application android:hasCode="false" />
+    <uses-sdk android:targetSdkVersion="29" />
+    <overlay android:targetPackage="com.android.perftests.core" android:targetName="TestResources"/>
+</manifest>
\ No newline at end of file
diff --git a/apct-tests/perftests/core/apps/overlay/res/values/values.xml b/apct-tests/perftests/core/apps/overlay/res/values/values.xml
new file mode 100644
index 0000000..a1a8d83
--- /dev/null
+++ b/apct-tests/perftests/core/apps/overlay/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="short_text">B</string>
+</resources>
diff --git a/apct-tests/perftests/core/apps/overlay/res_large/values/values.xml b/apct-tests/perftests/core/apps/overlay/res_large/values/values.xml
new file mode 100644
index 0000000..e741446
--- /dev/null
+++ b/apct-tests/perftests/core/apps/overlay/res_large/values/values.xml
@@ -0,0 +1,274 @@
+<?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="short_text000">B</string>
+  <string name="short_text001">B</string>
+  <string name="short_text002">B</string>
+  <string name="short_text003">B</string>
+  <string name="short_text004">B</string>
+  <string name="short_text005">B</string>
+  <string name="short_text006">B</string>
+  <string name="short_text007">B</string>
+  <string name="short_text008">B</string>
+  <string name="short_text009">B</string>
+  <string name="short_text010">B</string>
+  <string name="short_text011">B</string>
+  <string name="short_text012">B</string>
+  <string name="short_text013">B</string>
+  <string name="short_text014">B</string>
+  <string name="short_text015">B</string>
+  <string name="short_text016">B</string>
+  <string name="short_text017">B</string>
+  <string name="short_text018">B</string>
+  <string name="short_text019">B</string>
+  <string name="short_text020">B</string>
+  <string name="short_text021">B</string>
+  <string name="short_text022">B</string>
+  <string name="short_text023">B</string>
+  <string name="short_text024">B</string>
+  <string name="short_text025">B</string>
+  <string name="short_text026">B</string>
+  <string name="short_text027">B</string>
+  <string name="short_text028">B</string>
+  <string name="short_text029">B</string>
+  <string name="short_text030">B</string>
+  <string name="short_text031">B</string>
+  <string name="short_text032">B</string>
+  <string name="short_text033">B</string>
+  <string name="short_text034">B</string>
+  <string name="short_text035">B</string>
+  <string name="short_text036">B</string>
+  <string name="short_text037">B</string>
+  <string name="short_text038">B</string>
+  <string name="short_text039">B</string>
+  <string name="short_text040">B</string>
+  <string name="short_text041">B</string>
+  <string name="short_text042">B</string>
+  <string name="short_text043">B</string>
+  <string name="short_text044">B</string>
+  <string name="short_text045">B</string>
+  <string name="short_text046">B</string>
+  <string name="short_text047">B</string>
+  <string name="short_text048">B</string>
+  <string name="short_text049">B</string>
+  <string name="short_text050">B</string>
+  <string name="short_text051">B</string>
+  <string name="short_text052">B</string>
+  <string name="short_text053">B</string>
+  <string name="short_text054">B</string>
+  <string name="short_text055">B</string>
+  <string name="short_text056">B</string>
+  <string name="short_text057">B</string>
+  <string name="short_text058">B</string>
+  <string name="short_text059">B</string>
+  <string name="short_text060">B</string>
+  <string name="short_text061">B</string>
+  <string name="short_text062">B</string>
+  <string name="short_text063">B</string>
+  <string name="short_text064">B</string>
+  <string name="short_text065">B</string>
+  <string name="short_text066">B</string>
+  <string name="short_text067">B</string>
+  <string name="short_text068">B</string>
+  <string name="short_text069">B</string>
+  <string name="short_text070">B</string>
+  <string name="short_text071">B</string>
+  <string name="short_text072">B</string>
+  <string name="short_text073">B</string>
+  <string name="short_text074">B</string>
+  <string name="short_text075">B</string>
+  <string name="short_text076">B</string>
+  <string name="short_text077">B</string>
+  <string name="short_text078">B</string>
+  <string name="short_text079">B</string>
+  <string name="short_text080">B</string>
+  <string name="short_text081">B</string>
+  <string name="short_text082">B</string>
+  <string name="short_text083">B</string>
+  <string name="short_text084">B</string>
+  <string name="short_text085">B</string>
+  <string name="short_text086">B</string>
+  <string name="short_text087">B</string>
+  <string name="short_text088">B</string>
+  <string name="short_text089">B</string>
+  <string name="short_text090">B</string>
+  <string name="short_text091">B</string>
+  <string name="short_text092">B</string>
+  <string name="short_text093">B</string>
+  <string name="short_text094">B</string>
+  <string name="short_text095">B</string>
+  <string name="short_text096">B</string>
+  <string name="short_text097">B</string>
+  <string name="short_text098">B</string>
+  <string name="short_text099">B</string>
+  <string name="short_text100">B</string>
+  <string name="short_text101">B</string>
+  <string name="short_text102">B</string>
+  <string name="short_text103">B</string>
+  <string name="short_text104">B</string>
+  <string name="short_text105">B</string>
+  <string name="short_text106">B</string>
+  <string name="short_text107">B</string>
+  <string name="short_text108">B</string>
+  <string name="short_text109">B</string>
+  <string name="short_text110">B</string>
+  <string name="short_text111">B</string>
+  <string name="short_text112">B</string>
+  <string name="short_text113">B</string>
+  <string name="short_text114">B</string>
+  <string name="short_text115">B</string>
+  <string name="short_text116">B</string>
+  <string name="short_text117">B</string>
+  <string name="short_text118">B</string>
+  <string name="short_text119">B</string>
+  <string name="short_text120">B</string>
+  <string name="short_text121">B</string>
+  <string name="short_text122">B</string>
+  <string name="short_text123">B</string>
+  <string name="short_text124">B</string>
+  <string name="short_text125">B</string>
+  <string name="short_text126">B</string>
+  <string name="short_text127">B</string>
+  <string name="short_text128">B</string>
+  <string name="short_text129">B</string>
+  <string name="short_text130">B</string>
+  <string name="short_text131">B</string>
+  <string name="short_text132">B</string>
+  <string name="short_text133">B</string>
+  <string name="short_text134">B</string>
+  <string name="short_text135">B</string>
+  <string name="short_text136">B</string>
+  <string name="short_text137">B</string>
+  <string name="short_text138">B</string>
+  <string name="short_text139">B</string>
+  <string name="short_text140">B</string>
+  <string name="short_text141">B</string>
+  <string name="short_text142">B</string>
+  <string name="short_text143">B</string>
+  <string name="short_text144">B</string>
+  <string name="short_text145">B</string>
+  <string name="short_text146">B</string>
+  <string name="short_text147">B</string>
+  <string name="short_text148">B</string>
+  <string name="short_text149">B</string>
+  <string name="short_text150">B</string>
+  <string name="short_text151">B</string>
+  <string name="short_text152">B</string>
+  <string name="short_text153">B</string>
+  <string name="short_text154">B</string>
+  <string name="short_text155">B</string>
+  <string name="short_text156">B</string>
+  <string name="short_text157">B</string>
+  <string name="short_text158">B</string>
+  <string name="short_text159">B</string>
+  <string name="short_text160">B</string>
+  <string name="short_text161">B</string>
+  <string name="short_text162">B</string>
+  <string name="short_text163">B</string>
+  <string name="short_text164">B</string>
+  <string name="short_text165">B</string>
+  <string name="short_text166">B</string>
+  <string name="short_text167">B</string>
+  <string name="short_text168">B</string>
+  <string name="short_text169">B</string>
+  <string name="short_text170">B</string>
+  <string name="short_text171">B</string>
+  <string name="short_text172">B</string>
+  <string name="short_text173">B</string>
+  <string name="short_text174">B</string>
+  <string name="short_text175">B</string>
+  <string name="short_text176">B</string>
+  <string name="short_text177">B</string>
+  <string name="short_text178">B</string>
+  <string name="short_text179">B</string>
+  <string name="short_text180">B</string>
+  <string name="short_text181">B</string>
+  <string name="short_text182">B</string>
+  <string name="short_text183">B</string>
+  <string name="short_text184">B</string>
+  <string name="short_text185">B</string>
+  <string name="short_text186">B</string>
+  <string name="short_text187">B</string>
+  <string name="short_text188">B</string>
+  <string name="short_text189">B</string>
+  <string name="short_text190">B</string>
+  <string name="short_text191">B</string>
+  <string name="short_text192">B</string>
+  <string name="short_text193">B</string>
+  <string name="short_text194">B</string>
+  <string name="short_text195">B</string>
+  <string name="short_text196">B</string>
+  <string name="short_text197">B</string>
+  <string name="short_text198">B</string>
+  <string name="short_text199">B</string>
+  <string name="short_text200">B</string>
+  <string name="short_text201">B</string>
+  <string name="short_text202">B</string>
+  <string name="short_text203">B</string>
+  <string name="short_text204">B</string>
+  <string name="short_text205">B</string>
+  <string name="short_text206">B</string>
+  <string name="short_text207">B</string>
+  <string name="short_text208">B</string>
+  <string name="short_text209">B</string>
+  <string name="short_text210">B</string>
+  <string name="short_text211">B</string>
+  <string name="short_text212">B</string>
+  <string name="short_text213">B</string>
+  <string name="short_text214">B</string>
+  <string name="short_text215">B</string>
+  <string name="short_text216">B</string>
+  <string name="short_text217">B</string>
+  <string name="short_text218">B</string>
+  <string name="short_text219">B</string>
+  <string name="short_text220">B</string>
+  <string name="short_text221">B</string>
+  <string name="short_text222">B</string>
+  <string name="short_text223">B</string>
+  <string name="short_text224">B</string>
+  <string name="short_text225">B</string>
+  <string name="short_text226">B</string>
+  <string name="short_text227">B</string>
+  <string name="short_text228">B</string>
+  <string name="short_text229">B</string>
+  <string name="short_text230">B</string>
+  <string name="short_text231">B</string>
+  <string name="short_text232">B</string>
+  <string name="short_text233">B</string>
+  <string name="short_text234">B</string>
+  <string name="short_text235">B</string>
+  <string name="short_text236">B</string>
+  <string name="short_text237">B</string>
+  <string name="short_text238">B</string>
+  <string name="short_text239">B</string>
+  <string name="short_text240">B</string>
+  <string name="short_text241">B</string>
+  <string name="short_text242">B</string>
+  <string name="short_text243">B</string>
+  <string name="short_text244">B</string>
+  <string name="short_text245">B</string>
+  <string name="short_text246">B</string>
+  <string name="short_text247">B</string>
+  <string name="short_text248">B</string>
+  <string name="short_text249">B</string>
+  <string name="short_text250">B</string>
+  <string name="short_text251">B</string>
+  <string name="short_text252">B</string>
+  <string name="short_text253">B</string>
+  <string name="short_text254">B</string>
+  <string name="short_text255">B</string>
+</resources>
diff --git a/apct-tests/perftests/core/apps/reources_manager/Android.bp b/apct-tests/perftests/core/apps/reources_manager/Android.bp
new file mode 100644
index 0000000..4516132
--- /dev/null
+++ b/apct-tests/perftests/core/apps/reources_manager/Android.bp
@@ -0,0 +1,34 @@
+// 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_test_helper_app {
+    name: "LargeResourcesCompressed",
+    static_libs: [ "androidx.appcompat_appcompat" ],
+}
+
+genrule {
+    name: "LargeResourcesUncompressed",
+    srcs: [ ":LargeResourcesCompressed" ],
+    out: ["LargeResourcesUncompressed.apk"],
+    cmd: "cp $(in) $(out) && unzip -o $(out) resources.arsc"
+         + " && zip $(out) resources.arsc"
+}
+
+java_library {
+    name: "apct-perftests-resources-manager-apps",
+    java_resources: [
+        ":LargeResourcesCompressed",
+        ":LargeResourcesUncompressed",
+    ],
+}
\ No newline at end of file
diff --git a/apct-tests/perftests/core/apps/reources_manager/AndroidManifest.xml b/apct-tests/perftests/core/apps/reources_manager/AndroidManifest.xml
new file mode 100644
index 0000000..adb4e40
--- /dev/null
+++ b/apct-tests/perftests/core/apps/reources_manager/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 xmlns:android="http://schemas.android.com/apk/res/android"
+          package="fake.android">
+    <application android:hasCode="false" />
+    <uses-sdk android:targetSdkVersion="29" />
+</manifest>
\ No newline at end of file
diff --git a/apct-tests/perftests/core/res/color/color_state_list.xml b/apct-tests/perftests/core/res/color/color_state_list.xml
new file mode 100644
index 0000000..142e47a
--- /dev/null
+++ b/apct-tests/perftests/core/res/color/color_state_list.xml
@@ -0,0 +1,25 @@
+<?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.
+-->
+<selector xmlns:android="http://schemas.android.com/apk/res/android">
+    <item android:state_focused="true"
+        android:color="#000000" />
+    <item android:state_pressed="true"
+        android:state_enabled="false"
+        android:color="#212121" />
+    <item android:state_enabled="false"
+        android:color="#414141" />
+    <item android:color="#616161" />
+</selector>
\ No newline at end of file
diff --git a/apct-tests/perftests/core/res/values/overlayable.xml b/apct-tests/perftests/core/res/values/overlayable.xml
new file mode 100644
index 0000000..70cedd7
--- /dev/null
+++ b/apct-tests/perftests/core/res/values/overlayable.xml
@@ -0,0 +1,280 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  ~ Copyright (C) 2019 The Android Open Source Project
+  ~
+  ~ Licensed under the Apache License, Version 2.0 (the "License");
+  ~ you may not use this file except in compliance with the License.
+  ~ You may obtain a copy of the License at
+  ~
+  ~      http://www.apache.org/licenses/LICENSE-2.0
+  ~
+  ~ Unless required by applicable law or agreed to in writing, software
+  ~ distributed under the License is distributed on an "AS IS" BASIS,
+  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  ~ See the License for the specific language governing permissions and
+  ~ limitations under the License
+  -->
+
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <overlayable name="TestResources">
+        <policy type="public">
+            <item type="string" name="short_text" />
+             <item type="string" name="short_text000" />
+             <item type="string" name="short_text001" />
+             <item type="string" name="short_text002" />
+             <item type="string" name="short_text003" />
+             <item type="string" name="short_text004" />
+             <item type="string" name="short_text005" />
+             <item type="string" name="short_text006" />
+             <item type="string" name="short_text007" />
+             <item type="string" name="short_text008" />
+             <item type="string" name="short_text009" />
+             <item type="string" name="short_text010" />
+             <item type="string" name="short_text011" />
+             <item type="string" name="short_text012" />
+             <item type="string" name="short_text013" />
+             <item type="string" name="short_text014" />
+             <item type="string" name="short_text015" />
+             <item type="string" name="short_text016" />
+             <item type="string" name="short_text017" />
+             <item type="string" name="short_text018" />
+             <item type="string" name="short_text019" />
+             <item type="string" name="short_text020" />
+             <item type="string" name="short_text021" />
+             <item type="string" name="short_text022" />
+             <item type="string" name="short_text023" />
+             <item type="string" name="short_text024" />
+             <item type="string" name="short_text025" />
+             <item type="string" name="short_text026" />
+             <item type="string" name="short_text027" />
+             <item type="string" name="short_text028" />
+             <item type="string" name="short_text029" />
+             <item type="string" name="short_text030" />
+             <item type="string" name="short_text031" />
+             <item type="string" name="short_text032" />
+             <item type="string" name="short_text033" />
+             <item type="string" name="short_text034" />
+             <item type="string" name="short_text035" />
+             <item type="string" name="short_text036" />
+             <item type="string" name="short_text037" />
+             <item type="string" name="short_text038" />
+             <item type="string" name="short_text039" />
+             <item type="string" name="short_text040" />
+             <item type="string" name="short_text041" />
+             <item type="string" name="short_text042" />
+             <item type="string" name="short_text043" />
+             <item type="string" name="short_text044" />
+             <item type="string" name="short_text045" />
+             <item type="string" name="short_text046" />
+             <item type="string" name="short_text047" />
+             <item type="string" name="short_text048" />
+             <item type="string" name="short_text049" />
+             <item type="string" name="short_text050" />
+             <item type="string" name="short_text051" />
+             <item type="string" name="short_text052" />
+             <item type="string" name="short_text053" />
+             <item type="string" name="short_text054" />
+             <item type="string" name="short_text055" />
+             <item type="string" name="short_text056" />
+             <item type="string" name="short_text057" />
+             <item type="string" name="short_text058" />
+             <item type="string" name="short_text059" />
+             <item type="string" name="short_text060" />
+             <item type="string" name="short_text061" />
+             <item type="string" name="short_text062" />
+             <item type="string" name="short_text063" />
+             <item type="string" name="short_text064" />
+             <item type="string" name="short_text065" />
+             <item type="string" name="short_text066" />
+             <item type="string" name="short_text067" />
+             <item type="string" name="short_text068" />
+             <item type="string" name="short_text069" />
+             <item type="string" name="short_text070" />
+             <item type="string" name="short_text071" />
+             <item type="string" name="short_text072" />
+             <item type="string" name="short_text073" />
+             <item type="string" name="short_text074" />
+             <item type="string" name="short_text075" />
+             <item type="string" name="short_text076" />
+             <item type="string" name="short_text077" />
+             <item type="string" name="short_text078" />
+             <item type="string" name="short_text079" />
+             <item type="string" name="short_text080" />
+             <item type="string" name="short_text081" />
+             <item type="string" name="short_text082" />
+             <item type="string" name="short_text083" />
+             <item type="string" name="short_text084" />
+             <item type="string" name="short_text085" />
+             <item type="string" name="short_text086" />
+             <item type="string" name="short_text087" />
+             <item type="string" name="short_text088" />
+             <item type="string" name="short_text089" />
+             <item type="string" name="short_text090" />
+             <item type="string" name="short_text091" />
+             <item type="string" name="short_text092" />
+             <item type="string" name="short_text093" />
+             <item type="string" name="short_text094" />
+             <item type="string" name="short_text095" />
+             <item type="string" name="short_text096" />
+             <item type="string" name="short_text097" />
+             <item type="string" name="short_text098" />
+             <item type="string" name="short_text099" />
+             <item type="string" name="short_text100" />
+             <item type="string" name="short_text101" />
+             <item type="string" name="short_text102" />
+             <item type="string" name="short_text103" />
+             <item type="string" name="short_text104" />
+             <item type="string" name="short_text105" />
+             <item type="string" name="short_text106" />
+             <item type="string" name="short_text107" />
+             <item type="string" name="short_text108" />
+             <item type="string" name="short_text109" />
+             <item type="string" name="short_text110" />
+             <item type="string" name="short_text111" />
+             <item type="string" name="short_text112" />
+             <item type="string" name="short_text113" />
+             <item type="string" name="short_text114" />
+             <item type="string" name="short_text115" />
+             <item type="string" name="short_text116" />
+             <item type="string" name="short_text117" />
+             <item type="string" name="short_text118" />
+             <item type="string" name="short_text119" />
+             <item type="string" name="short_text120" />
+             <item type="string" name="short_text121" />
+             <item type="string" name="short_text122" />
+             <item type="string" name="short_text123" />
+             <item type="string" name="short_text124" />
+             <item type="string" name="short_text125" />
+             <item type="string" name="short_text126" />
+             <item type="string" name="short_text127" />
+             <item type="string" name="short_text128" />
+             <item type="string" name="short_text129" />
+             <item type="string" name="short_text130" />
+             <item type="string" name="short_text131" />
+             <item type="string" name="short_text132" />
+             <item type="string" name="short_text133" />
+             <item type="string" name="short_text134" />
+             <item type="string" name="short_text135" />
+             <item type="string" name="short_text136" />
+             <item type="string" name="short_text137" />
+             <item type="string" name="short_text138" />
+             <item type="string" name="short_text139" />
+             <item type="string" name="short_text140" />
+             <item type="string" name="short_text141" />
+             <item type="string" name="short_text142" />
+             <item type="string" name="short_text143" />
+             <item type="string" name="short_text144" />
+             <item type="string" name="short_text145" />
+             <item type="string" name="short_text146" />
+             <item type="string" name="short_text147" />
+             <item type="string" name="short_text148" />
+             <item type="string" name="short_text149" />
+             <item type="string" name="short_text150" />
+             <item type="string" name="short_text151" />
+             <item type="string" name="short_text152" />
+             <item type="string" name="short_text153" />
+             <item type="string" name="short_text154" />
+             <item type="string" name="short_text155" />
+             <item type="string" name="short_text156" />
+             <item type="string" name="short_text157" />
+             <item type="string" name="short_text158" />
+             <item type="string" name="short_text159" />
+             <item type="string" name="short_text160" />
+             <item type="string" name="short_text161" />
+             <item type="string" name="short_text162" />
+             <item type="string" name="short_text163" />
+             <item type="string" name="short_text164" />
+             <item type="string" name="short_text165" />
+             <item type="string" name="short_text166" />
+             <item type="string" name="short_text167" />
+             <item type="string" name="short_text168" />
+             <item type="string" name="short_text169" />
+             <item type="string" name="short_text170" />
+             <item type="string" name="short_text171" />
+             <item type="string" name="short_text172" />
+             <item type="string" name="short_text173" />
+             <item type="string" name="short_text174" />
+             <item type="string" name="short_text175" />
+             <item type="string" name="short_text176" />
+             <item type="string" name="short_text177" />
+             <item type="string" name="short_text178" />
+             <item type="string" name="short_text179" />
+             <item type="string" name="short_text180" />
+             <item type="string" name="short_text181" />
+             <item type="string" name="short_text182" />
+             <item type="string" name="short_text183" />
+             <item type="string" name="short_text184" />
+             <item type="string" name="short_text185" />
+             <item type="string" name="short_text186" />
+             <item type="string" name="short_text187" />
+             <item type="string" name="short_text188" />
+             <item type="string" name="short_text189" />
+             <item type="string" name="short_text190" />
+             <item type="string" name="short_text191" />
+             <item type="string" name="short_text192" />
+             <item type="string" name="short_text193" />
+             <item type="string" name="short_text194" />
+             <item type="string" name="short_text195" />
+             <item type="string" name="short_text196" />
+             <item type="string" name="short_text197" />
+             <item type="string" name="short_text198" />
+             <item type="string" name="short_text199" />
+             <item type="string" name="short_text200" />
+             <item type="string" name="short_text201" />
+             <item type="string" name="short_text202" />
+             <item type="string" name="short_text203" />
+             <item type="string" name="short_text204" />
+             <item type="string" name="short_text205" />
+             <item type="string" name="short_text206" />
+             <item type="string" name="short_text207" />
+             <item type="string" name="short_text208" />
+             <item type="string" name="short_text209" />
+             <item type="string" name="short_text210" />
+             <item type="string" name="short_text211" />
+             <item type="string" name="short_text212" />
+             <item type="string" name="short_text213" />
+             <item type="string" name="short_text214" />
+             <item type="string" name="short_text215" />
+             <item type="string" name="short_text216" />
+             <item type="string" name="short_text217" />
+             <item type="string" name="short_text218" />
+             <item type="string" name="short_text219" />
+             <item type="string" name="short_text220" />
+             <item type="string" name="short_text221" />
+             <item type="string" name="short_text222" />
+             <item type="string" name="short_text223" />
+             <item type="string" name="short_text224" />
+             <item type="string" name="short_text225" />
+             <item type="string" name="short_text226" />
+             <item type="string" name="short_text227" />
+             <item type="string" name="short_text228" />
+             <item type="string" name="short_text229" />
+             <item type="string" name="short_text230" />
+             <item type="string" name="short_text231" />
+             <item type="string" name="short_text232" />
+             <item type="string" name="short_text233" />
+             <item type="string" name="short_text234" />
+             <item type="string" name="short_text235" />
+             <item type="string" name="short_text236" />
+             <item type="string" name="short_text237" />
+             <item type="string" name="short_text238" />
+             <item type="string" name="short_text239" />
+             <item type="string" name="short_text240" />
+             <item type="string" name="short_text241" />
+             <item type="string" name="short_text242" />
+             <item type="string" name="short_text243" />
+             <item type="string" name="short_text244" />
+             <item type="string" name="short_text245" />
+             <item type="string" name="short_text246" />
+             <item type="string" name="short_text247" />
+             <item type="string" name="short_text248" />
+             <item type="string" name="short_text249" />
+             <item type="string" name="short_text250" />
+             <item type="string" name="short_text251" />
+             <item type="string" name="short_text252" />
+             <item type="string" name="short_text253" />
+             <item type="string" name="short_text254" />
+             <item type="string" name="short_text255" />
+        </policy>
+    </overlayable>
+</resources>
diff --git a/apct-tests/perftests/core/res/values/strings.xml b/apct-tests/perftests/core/res/values/strings.xml
deleted file mode 100644
index 7ab325f..0000000
--- a/apct-tests/perftests/core/res/values/strings.xml
+++ /dev/null
@@ -1,32 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-  ~ 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
-  -->
-
-<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="long_text">text text text text text text text text text text text text
-        text text text text text text text text text text text text text text text text
-        text text text text text text text text text text text text text text text text
-        text text text text text text text text text text text text text text text text
-        text text text text text text text text text text text text text text text text
-        text text text text text text text text text text text text text text text text
-        text text text text text text text typo text text text text text text text text
-        text text text text text text text text text text text text text text text text
-        text text text text text text text text text text text text text text text text
-        text text text text text text text text text text text text text text text text
-        text text text text text text text text text text text text text text text text
-        text text text text text text text text text text text text </string>
-    <string name="short_text">text text</string>
-</resources>
diff --git a/apct-tests/perftests/core/res/values/values.xml b/apct-tests/perftests/core/res/values/values.xml
new file mode 100644
index 0000000..aad42ba
--- /dev/null
+++ b/apct-tests/perftests/core/res/values/values.xml
@@ -0,0 +1,368 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  ~ 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
+  -->
+
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="long_text">text text text text text text text text text text text text
+        text text text text text text text text text text text text text text text text
+        text text text text text text text text text text text text text text text text
+        text text text text text text text text text text text text text text text text
+        text text text text text text text text text text text text text text text text
+        text text text text text text text text text text text text text text text text
+        text text text text text text text typo text text text text text text text text
+        text text text text text text text text text text text text text text text text
+        text text text text text text text text text text text text text text text text
+        text text text text text text text text text text text text text text text text
+        text text text text text text text text text text text text text text text text
+        text text text text text text text text text text text text </string>
+
+    <plurals name="plurals_text">
+        <item quantity="one">1 text</item>
+        <item quantity="other"><xliff:g id="count" example="3">%d</xliff:g> texts</item>
+    </plurals>
+
+    <string-array name="strings">
+        <item>Run</item>
+        <item>the</item>
+        <item>performance</item>
+        <item>tests!</item>
+        <item>Run</item>
+        <item>the</item>
+        <item>performance</item>
+        <item>tests!</item>
+        <item>Run</item>
+        <item>the</item>
+        <item>performance</item>
+        <item>tests!</item>
+        <item>Run</item>
+        <item>the</item>
+        <item>performance</item>
+        <item>tests!</item>
+        <item>Run</item>
+        <item>the</item>
+        <item>performance</item>
+        <item>tests!</item>
+        <item>Run</item>
+        <item>the</item>
+        <item>performance</item>
+        <item>tests!</item>
+        <item>Run</item>
+        <item>the</item>
+        <item>performance</item>
+        <item>tests!</item>
+        <item>Run</item>
+        <item>the</item>
+        <item>performance</item>
+        <item>tests!</item>
+    </string-array>
+
+    <integer-array name="ints">
+        <item>0</item>
+        <item>1</item>
+        <item>2</item>
+        <item>3</item>
+        <item>0</item>
+        <item>1</item>
+        <item>2</item>
+        <item>3</item>
+        <item>0</item>
+        <item>1</item>
+        <item>2</item>
+        <item>3</item>
+        <item>0</item>
+        <item>1</item>
+        <item>2</item>
+        <item>3</item>
+        <item>0</item>
+        <item>1</item>
+        <item>2</item>
+        <item>3</item>
+        <item>0</item>
+        <item>1</item>
+        <item>2</item>
+        <item>3</item>
+        <item>0</item>
+        <item>1</item>
+        <item>2</item>
+        <item>3</item>
+        <item>0</item>
+        <item>1</item>
+        <item>2</item>
+        <item>3</item>
+    </integer-array>
+
+    <color name="white">#ffffff</color>
+
+    <integer name="forty_two">42</integer>
+
+    <string name="short_text">text text</string>
+    <string name="short_text000">B</string>
+    <string name="short_text001">B</string>
+    <string name="short_text002">B</string>
+    <string name="short_text003">B</string>
+    <string name="short_text004">B</string>
+    <string name="short_text005">B</string>
+    <string name="short_text006">B</string>
+    <string name="short_text007">B</string>
+    <string name="short_text008">B</string>
+    <string name="short_text009">B</string>
+    <string name="short_text010">B</string>
+    <string name="short_text011">B</string>
+    <string name="short_text012">B</string>
+    <string name="short_text013">B</string>
+    <string name="short_text014">B</string>
+    <string name="short_text015">B</string>
+    <string name="short_text016">B</string>
+    <string name="short_text017">B</string>
+    <string name="short_text018">B</string>
+    <string name="short_text019">B</string>
+    <string name="short_text020">B</string>
+    <string name="short_text021">B</string>
+    <string name="short_text022">B</string>
+    <string name="short_text023">B</string>
+    <string name="short_text024">B</string>
+    <string name="short_text025">B</string>
+    <string name="short_text026">B</string>
+    <string name="short_text027">B</string>
+    <string name="short_text028">B</string>
+    <string name="short_text029">B</string>
+    <string name="short_text030">B</string>
+    <string name="short_text031">B</string>
+    <string name="short_text032">B</string>
+    <string name="short_text033">B</string>
+    <string name="short_text034">B</string>
+    <string name="short_text035">B</string>
+    <string name="short_text036">B</string>
+    <string name="short_text037">B</string>
+    <string name="short_text038">B</string>
+    <string name="short_text039">B</string>
+    <string name="short_text040">B</string>
+    <string name="short_text041">B</string>
+    <string name="short_text042">B</string>
+    <string name="short_text043">B</string>
+    <string name="short_text044">B</string>
+    <string name="short_text045">B</string>
+    <string name="short_text046">B</string>
+    <string name="short_text047">B</string>
+    <string name="short_text048">B</string>
+    <string name="short_text049">B</string>
+    <string name="short_text050">B</string>
+    <string name="short_text051">B</string>
+    <string name="short_text052">B</string>
+    <string name="short_text053">B</string>
+    <string name="short_text054">B</string>
+    <string name="short_text055">B</string>
+    <string name="short_text056">B</string>
+    <string name="short_text057">B</string>
+    <string name="short_text058">B</string>
+    <string name="short_text059">B</string>
+    <string name="short_text060">B</string>
+    <string name="short_text061">B</string>
+    <string name="short_text062">B</string>
+    <string name="short_text063">B</string>
+    <string name="short_text064">B</string>
+    <string name="short_text065">B</string>
+    <string name="short_text066">B</string>
+    <string name="short_text067">B</string>
+    <string name="short_text068">B</string>
+    <string name="short_text069">B</string>
+    <string name="short_text070">B</string>
+    <string name="short_text071">B</string>
+    <string name="short_text072">B</string>
+    <string name="short_text073">B</string>
+    <string name="short_text074">B</string>
+    <string name="short_text075">B</string>
+    <string name="short_text076">B</string>
+    <string name="short_text077">B</string>
+    <string name="short_text078">B</string>
+    <string name="short_text079">B</string>
+    <string name="short_text080">B</string>
+    <string name="short_text081">B</string>
+    <string name="short_text082">B</string>
+    <string name="short_text083">B</string>
+    <string name="short_text084">B</string>
+    <string name="short_text085">B</string>
+    <string name="short_text086">B</string>
+    <string name="short_text087">B</string>
+    <string name="short_text088">B</string>
+    <string name="short_text089">B</string>
+    <string name="short_text090">B</string>
+    <string name="short_text091">B</string>
+    <string name="short_text092">B</string>
+    <string name="short_text093">B</string>
+    <string name="short_text094">B</string>
+    <string name="short_text095">B</string>
+    <string name="short_text096">B</string>
+    <string name="short_text097">B</string>
+    <string name="short_text098">B</string>
+    <string name="short_text099">B</string>
+    <string name="short_text100">B</string>
+    <string name="short_text101">B</string>
+    <string name="short_text102">B</string>
+    <string name="short_text103">B</string>
+    <string name="short_text104">B</string>
+    <string name="short_text105">B</string>
+    <string name="short_text106">B</string>
+    <string name="short_text107">B</string>
+    <string name="short_text108">B</string>
+    <string name="short_text109">B</string>
+    <string name="short_text110">B</string>
+    <string name="short_text111">B</string>
+    <string name="short_text112">B</string>
+    <string name="short_text113">B</string>
+    <string name="short_text114">B</string>
+    <string name="short_text115">B</string>
+    <string name="short_text116">B</string>
+    <string name="short_text117">B</string>
+    <string name="short_text118">B</string>
+    <string name="short_text119">B</string>
+    <string name="short_text120">B</string>
+    <string name="short_text121">B</string>
+    <string name="short_text122">B</string>
+    <string name="short_text123">B</string>
+    <string name="short_text124">B</string>
+    <string name="short_text125">B</string>
+    <string name="short_text126">B</string>
+    <string name="short_text127">B</string>
+    <string name="short_text128">B</string>
+    <string name="short_text129">B</string>
+    <string name="short_text130">B</string>
+    <string name="short_text131">B</string>
+    <string name="short_text132">B</string>
+    <string name="short_text133">B</string>
+    <string name="short_text134">B</string>
+    <string name="short_text135">B</string>
+    <string name="short_text136">B</string>
+    <string name="short_text137">B</string>
+    <string name="short_text138">B</string>
+    <string name="short_text139">B</string>
+    <string name="short_text140">B</string>
+    <string name="short_text141">B</string>
+    <string name="short_text142">B</string>
+    <string name="short_text143">B</string>
+    <string name="short_text144">B</string>
+    <string name="short_text145">B</string>
+    <string name="short_text146">B</string>
+    <string name="short_text147">B</string>
+    <string name="short_text148">B</string>
+    <string name="short_text149">B</string>
+    <string name="short_text150">B</string>
+    <string name="short_text151">B</string>
+    <string name="short_text152">B</string>
+    <string name="short_text153">B</string>
+    <string name="short_text154">B</string>
+    <string name="short_text155">B</string>
+    <string name="short_text156">B</string>
+    <string name="short_text157">B</string>
+    <string name="short_text158">B</string>
+    <string name="short_text159">B</string>
+    <string name="short_text160">B</string>
+    <string name="short_text161">B</string>
+    <string name="short_text162">B</string>
+    <string name="short_text163">B</string>
+    <string name="short_text164">B</string>
+    <string name="short_text165">B</string>
+    <string name="short_text166">B</string>
+    <string name="short_text167">B</string>
+    <string name="short_text168">B</string>
+    <string name="short_text169">B</string>
+    <string name="short_text170">B</string>
+    <string name="short_text171">B</string>
+    <string name="short_text172">B</string>
+    <string name="short_text173">B</string>
+    <string name="short_text174">B</string>
+    <string name="short_text175">B</string>
+    <string name="short_text176">B</string>
+    <string name="short_text177">B</string>
+    <string name="short_text178">B</string>
+    <string name="short_text179">B</string>
+    <string name="short_text180">B</string>
+    <string name="short_text181">B</string>
+    <string name="short_text182">B</string>
+    <string name="short_text183">B</string>
+    <string name="short_text184">B</string>
+    <string name="short_text185">B</string>
+    <string name="short_text186">B</string>
+    <string name="short_text187">B</string>
+    <string name="short_text188">B</string>
+    <string name="short_text189">B</string>
+    <string name="short_text190">B</string>
+    <string name="short_text191">B</string>
+    <string name="short_text192">B</string>
+    <string name="short_text193">B</string>
+    <string name="short_text194">B</string>
+    <string name="short_text195">B</string>
+    <string name="short_text196">B</string>
+    <string name="short_text197">B</string>
+    <string name="short_text198">B</string>
+    <string name="short_text199">B</string>
+    <string name="short_text200">B</string>
+    <string name="short_text201">B</string>
+    <string name="short_text202">B</string>
+    <string name="short_text203">B</string>
+    <string name="short_text204">B</string>
+    <string name="short_text205">B</string>
+    <string name="short_text206">B</string>
+    <string name="short_text207">B</string>
+    <string name="short_text208">B</string>
+    <string name="short_text209">B</string>
+    <string name="short_text210">B</string>
+    <string name="short_text211">B</string>
+    <string name="short_text212">B</string>
+    <string name="short_text213">B</string>
+    <string name="short_text214">B</string>
+    <string name="short_text215">B</string>
+    <string name="short_text216">B</string>
+    <string name="short_text217">B</string>
+    <string name="short_text218">B</string>
+    <string name="short_text219">B</string>
+    <string name="short_text220">B</string>
+    <string name="short_text221">B</string>
+    <string name="short_text222">B</string>
+    <string name="short_text223">B</string>
+    <string name="short_text224">B</string>
+    <string name="short_text225">B</string>
+    <string name="short_text226">B</string>
+    <string name="short_text227">B</string>
+    <string name="short_text228">B</string>
+    <string name="short_text229">B</string>
+    <string name="short_text230">B</string>
+    <string name="short_text231">B</string>
+    <string name="short_text232">B</string>
+    <string name="short_text233">B</string>
+    <string name="short_text234">B</string>
+    <string name="short_text235">B</string>
+    <string name="short_text236">B</string>
+    <string name="short_text237">B</string>
+    <string name="short_text238">B</string>
+    <string name="short_text239">B</string>
+    <string name="short_text240">B</string>
+    <string name="short_text241">B</string>
+    <string name="short_text242">B</string>
+    <string name="short_text243">B</string>
+    <string name="short_text244">B</string>
+    <string name="short_text245">B</string>
+    <string name="short_text246">B</string>
+    <string name="short_text247">B</string>
+    <string name="short_text248">B</string>
+    <string name="short_text249">B</string>
+    <string name="short_text250">B</string>
+    <string name="short_text251">B</string>
+    <string name="short_text252">B</string>
+    <string name="short_text253">B</string>
+    <string name="short_text254">B</string>
+    <string name="short_text255">B</string>
+</resources>
diff --git a/apct-tests/perftests/core/src/android/app/OverlayManagerPerfTest.java b/apct-tests/perftests/core/src/android/app/OverlayManagerPerfTest.java
new file mode 100644
index 0000000..fcb13a8
--- /dev/null
+++ b/apct-tests/perftests/core/src/android/app/OverlayManagerPerfTest.java
@@ -0,0 +1,234 @@
+/*
+ * 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;
+
+import static org.junit.Assert.assertTrue;
+
+import android.content.Context;
+import android.content.om.OverlayManager;
+import android.os.UserHandle;
+import android.perftests.utils.BenchmarkState;
+import android.perftests.utils.PerfStatusReporter;
+import android.perftests.utils.TestPackageInstaller;
+
+import androidx.test.InstrumentationRegistry;
+import androidx.test.filters.LargeTest;
+
+import com.android.perftests.core.R;
+
+import org.junit.After;
+import org.junit.AfterClass;
+import org.junit.BeforeClass;
+import org.junit.Rule;
+import org.junit.Test;
+
+import java.util.ArrayList;
+import java.util.concurrent.Executor;
+import java.util.concurrent.FutureTask;
+import java.util.concurrent.TimeUnit;
+
+/**
+ * Benchmarks for {@link android.content.om.OverlayManager}.
+ */
+@LargeTest
+public class OverlayManagerPerfTest {
+    private static final int OVERLAY_PKG_COUNT = 10;
+    private static Context sContext;
+    private static OverlayManager sOverlayManager;
+    private static Executor sExecutor;
+    private static ArrayList<TestPackageInstaller.InstalledPackage> sSmallOverlays =
+            new ArrayList<>();
+    private static ArrayList<TestPackageInstaller.InstalledPackage> sLargeOverlays =
+            new ArrayList<>();
+
+    @Rule
+    public PerfStatusReporter mPerfStatusReporter = new PerfStatusReporter();
+
+    @BeforeClass
+    public static void classSetUp() throws Exception {
+        sContext = InstrumentationRegistry.getTargetContext();
+        sOverlayManager = new OverlayManager(sContext);
+        sExecutor = (command) -> new Thread(command).start();
+
+        // Install all of the test overlays.
+        TestPackageInstaller installer = new TestPackageInstaller(sContext);
+        for (int i = 0; i < OVERLAY_PKG_COUNT; i++) {
+            sSmallOverlays.add(installer.installPackage("Overlay" + i +".apk"));
+            sLargeOverlays.add(installer.installPackage("LargeOverlay" + i +".apk"));
+        }
+    }
+
+    @AfterClass
+    public static void classTearDown() throws Exception {
+        for (TestPackageInstaller.InstalledPackage overlay : sSmallOverlays) {
+            overlay.uninstall();
+        }
+
+        for (TestPackageInstaller.InstalledPackage overlay : sLargeOverlays) {
+            overlay.uninstall();
+        }
+    }
+
+    @After
+    public void tearDown() throws Exception {
+        // Disable all test overlays after each test.
+        for (TestPackageInstaller.InstalledPackage overlay : sSmallOverlays) {
+            assertSetEnabled(sContext, overlay.getPackageName(), false);
+        }
+
+        for (TestPackageInstaller.InstalledPackage overlay : sLargeOverlays) {
+            assertSetEnabled(sContext, overlay.getPackageName(), false);
+        }
+    }
+
+    /**
+     * Enables the overlay and waits for the APK path change sto be propagated to the context
+     * AssetManager.
+     */
+    private void assertSetEnabled(Context context, String overlayPackage, boolean eanabled)
+            throws Exception {
+        sOverlayManager.setEnabled(overlayPackage, true, UserHandle.SYSTEM);
+
+        // Wait for the overlay changes to propagate
+        FutureTask<Boolean> task = new FutureTask<>(() -> {
+            while (true) {
+                for (String path : context.getAssets().getApkPaths()) {
+                    if (eanabled == path.contains(overlayPackage)) {
+                        return true;
+                    }
+                }
+            }
+        });
+
+        sExecutor.execute(task);
+        assertTrue("Failed to load overlay " + overlayPackage,
+                task.get(20, TimeUnit.SECONDS));
+    }
+
+    @Test
+    public void setEnabledWarmCache() throws Exception {
+        String packageName = sSmallOverlays.get(0).getPackageName();
+        BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
+        while (state.keepRunning()) {
+            assertSetEnabled(sContext, packageName, true);
+
+            // Disable the overlay for the next iteration of the test
+            state.pauseTiming();
+            assertSetEnabled(sContext, packageName, false);
+            state.resumeTiming();
+        }
+    }
+
+    @Test
+    public void setEnabledColdCacheSmallOverlay() throws Exception {
+        String packageName = sSmallOverlays.get(0).getPackageName();
+        BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
+        while (state.keepRunning()) {
+            assertSetEnabled(sContext, packageName, true);
+
+            // Disable the overlay and remove the idmap for the next iteration of the test
+            state.pauseTiming();
+            assertSetEnabled(sContext, packageName, false);
+            sOverlayManager.invalidateCachesForOverlay(packageName, UserHandle.SYSTEM);
+            state.resumeTiming();
+        }
+    }
+
+    @Test
+    public void setEnabledColdCacheLargeOverlay() throws Exception {
+        String packageName = sLargeOverlays.get(0).getPackageName();
+        BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
+        while (state.keepRunning()) {
+            assertSetEnabled(sContext, packageName, true);
+
+            // Disable the overlay and remove the idmap for the next iteration of the test
+            state.pauseTiming();
+            assertSetEnabled(sContext, packageName, false);
+            sOverlayManager.invalidateCachesForOverlay(packageName, UserHandle.SYSTEM);
+            state.resumeTiming();
+        }
+    }
+
+    @Test
+    public void setEnabledDisable() throws Exception {
+        String packageName = sSmallOverlays.get(0).getPackageName();
+        BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
+        while (state.keepRunning()) {
+            state.pauseTiming();
+            assertSetEnabled(sContext, packageName, true);
+            state.resumeTiming();
+
+            assertSetEnabled(sContext, packageName, false);
+        }
+    }
+
+    @Test
+    public void getStringOneSmallOverlay() throws Exception {
+        String packageName = sSmallOverlays.get(0).getPackageName();
+        assertSetEnabled(sContext, packageName, true);
+
+        BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
+        while (state.keepRunning()) {
+            sContext.getString(R.string.short_text);
+        }
+
+        assertSetEnabled(sContext, packageName, false);
+    }
+
+    @Test
+    public void getStringOneLargeOverlay() throws Exception {
+        String packageName = sLargeOverlays.get(0).getPackageName();
+        assertSetEnabled(sContext, packageName, true);
+
+        BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
+        while (state.keepRunning()) {
+            for (int resId = R.string.short_text000; resId < R.string.short_text255; resId++) {
+                sContext.getString(resId);
+            }
+        }
+
+        assertSetEnabled(sContext, packageName, false);
+    }
+
+    @Test
+    public void getStringTenOverlays() throws Exception {
+        // Enable all test overlays
+        for (TestPackageInstaller.InstalledPackage overlay : sSmallOverlays) {
+            assertSetEnabled(sContext, overlay.getPackageName(), true);
+        }
+
+        BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
+        while (state.keepRunning()) {
+            sContext.getString(R.string.short_text);
+        }
+    }
+
+    @Test
+    public void getStringLargeTenOverlays() throws Exception {
+        // Enable all test overlays
+        for (TestPackageInstaller.InstalledPackage overlay : sLargeOverlays) {
+            assertSetEnabled(sContext, overlay.getPackageName(), true);
+        }
+
+        BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
+        while (state.keepRunning()) {
+            for (int resId = R.string.short_text000; resId < R.string.short_text255; resId++) {
+                sContext.getString(resId);
+            }
+        }
+    }
+}
diff --git a/apct-tests/perftests/core/src/android/app/ResourcesManagerPerfTest.java b/apct-tests/perftests/core/src/android/app/ResourcesManagerPerfTest.java
new file mode 100644
index 0000000..2955d2c
--- /dev/null
+++ b/apct-tests/perftests/core/src/android/app/ResourcesManagerPerfTest.java
@@ -0,0 +1,139 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package android.app;
+
+import android.content.Context;
+import android.content.res.Configuration;
+import android.content.res.Resources;
+import android.perftests.utils.BenchmarkState;
+import android.perftests.utils.PerfStatusReporter;
+import android.view.Display;
+
+import androidx.test.InstrumentationRegistry;
+import androidx.test.filters.LargeTest;
+
+import org.junit.AfterClass;
+import org.junit.Assert;
+import org.junit.BeforeClass;
+import org.junit.Rule;
+import org.junit.Test;
+
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.InputStream;
+import java.io.OutputStream;
+
+/**
+ * Benchmarks for {@link android.app.ResourcesManager}.
+ */
+@LargeTest
+public class ResourcesManagerPerfTest {
+    private static Context sContext;
+    private static File sResourcesCompressed;
+    private static File sResourcesUncompressed;
+
+    @Rule
+    public PerfStatusReporter mPerfStatusReporter = new PerfStatusReporter();
+
+    @BeforeClass
+    public static void setUp() throws Exception {
+        sContext = InstrumentationRegistry.getTargetContext();
+        sResourcesCompressed = copyApkToTemp("LargeResourcesCompressed.apk",
+                "LargeResourcesCompressed.apk");
+        sResourcesUncompressed = copyApkToTemp("LargeResourcesUncompressed.apk",
+                "LargeResourcesUncompressed.apk");
+    }
+
+    @AfterClass
+    public static void tearDown() {
+        Assert.assertTrue(sResourcesCompressed.delete());
+        Assert.assertTrue(sResourcesUncompressed.delete());
+    }
+
+    private static File copyApkToTemp(String inputFileName, String fileName) throws Exception {
+        File file = File.createTempFile(fileName, null, sContext.getCacheDir());
+        try (OutputStream tempOutputStream = new FileOutputStream(file);
+             InputStream is = sContext.getResources().getAssets().openNonAsset(inputFileName)) {
+            byte[] buffer = new byte[4096];
+            int n;
+            while ((n = is.read(buffer)) >= 0) {
+                tempOutputStream.write(buffer, 0, n);
+            }
+            tempOutputStream.flush();
+        }
+        return file;
+    }
+
+    private void getResourcesForPath(String path) {
+        ResourcesManager.getInstance().getResources(null, path, null, null, null,
+                Display.DEFAULT_DISPLAY, null, sContext.getResources().getCompatibilityInfo(),
+                null);
+    }
+
+    @Test
+    public void getResourcesCached() {
+        final BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
+        getResourcesForPath(sResourcesCompressed.getPath());
+        while (state.keepRunning()) {
+            getResourcesForPath(sResourcesCompressed.getPath());
+        }
+    }
+
+    @Test
+    public void getResourcesCompressedUncached() {
+        ResourcesManager resourcesManager = ResourcesManager.getInstance();
+        final BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
+        while (state.keepRunning()) {
+            state.pauseTiming();
+            resourcesManager.invalidatePath(sResourcesCompressed.getPath());
+            state.resumeTiming();
+
+            getResourcesForPath(sResourcesCompressed.getPath());
+        }
+    }
+
+    @Test
+    public void getResourcesUncompressedUncached() {
+        ResourcesManager resourcesManager = ResourcesManager.getInstance();
+        final BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
+        while (state.keepRunning()) {
+            state.pauseTiming();
+            resourcesManager.invalidatePath(sResourcesUncompressed.getPath());
+            state.resumeTiming();
+
+            getResourcesForPath(sResourcesUncompressed.getPath());
+        }
+    }
+
+    @Test
+    public void applyConfigurationToResourcesLocked() {
+        ResourcesManager resourcesManager = ResourcesManager.getInstance();
+        Configuration c = new Configuration(resourcesManager.getConfiguration());
+        c.uiMode = Configuration.UI_MODE_TYPE_WATCH;
+
+        final BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
+        while (state.keepRunning()) {
+            resourcesManager.applyConfigurationToResources(c, null);
+
+            // Alternate configurations to ensure the set configuration is different each iteration
+            if (c.uiMode == Configuration.UI_MODE_TYPE_WATCH) {
+                c.uiMode = Configuration.UI_MODE_TYPE_TELEVISION;
+            } else {
+                c.uiMode = Configuration.UI_MODE_TYPE_WATCH;
+            }
+        }
+    }
+}
diff --git a/apct-tests/perftests/core/src/android/app/ResourcesPerfTest.java b/apct-tests/perftests/core/src/android/app/ResourcesPerfTest.java
index c3e43ee..7216244 100644
--- a/apct-tests/perftests/core/src/android/app/ResourcesPerfTest.java
+++ b/apct-tests/perftests/core/src/android/app/ResourcesPerfTest.java
@@ -18,15 +18,18 @@
 
 import static org.junit.Assert.fail;
 
-import android.content.res.AssetManager;
+import android.content.Context;
 import android.content.res.Resources;
 import android.content.res.XmlResourceParser;
 import android.perftests.utils.BenchmarkState;
 import android.perftests.utils.PerfStatusReporter;
+import android.util.TypedValue;
 
+import androidx.test.InstrumentationRegistry;
 import androidx.test.filters.LargeTest;
 
-import org.junit.After;
+import com.android.perftests.core.R;
+
 import org.junit.Before;
 import org.junit.Rule;
 import org.junit.Test;
@@ -43,36 +46,123 @@
     @Rule
     public PerfStatusReporter mPerfStatusReporter = new PerfStatusReporter();
 
-    private AssetManager mAsset;
     private Resources mRes;
 
-    private int mTextId;
-    private int mColorId;
-    private int mIntegerId;
-    private int mLayoutId;
-
     @Before
     public void setUp() {
-        mAsset = new AssetManager();
-        mAsset.addAssetPath("/system/framework/framework-res.apk");
-        mRes = new Resources(mAsset, null, null);
-
-        mTextId = mRes.getIdentifier("cancel", "string", "android");
-        mColorId = mRes.getIdentifier("transparent", "color", "android");
-        mIntegerId = mRes.getIdentifier("config_shortAnimTime", "integer", "android");
-        mLayoutId = mRes.getIdentifier("two_line_list_item", "layout", "android");
+        Context context = InstrumentationRegistry.getTargetContext();
+        mRes = context.getResources();
     }
 
-    @After
-    public void tearDown() {
-        mAsset.close();
+    @Test
+    public void getValue() {
+        final BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
+        TypedValue value = new TypedValue();
+        while (state.keepRunning()) {
+            mRes.getValue(R.integer.forty_two, value, false /* resolve_refs */);
+        }
+    }
+
+    @Test
+    public void getFrameworkValue() {
+        final BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
+        TypedValue value = new TypedValue();
+        while (state.keepRunning()) {
+            mRes.getValue(com.android.internal.R.integer.autofill_max_visible_datasets, value,
+                    false /* resolve_refs */);
+        }
+    }
+
+    @Test
+    public void getValueString() {
+        final BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
+        TypedValue value = new TypedValue();
+        while (state.keepRunning()) {
+            mRes.getValue(R.string.long_text, value, false /* resolve_refs */);
+        }
+    }
+
+    @Test
+    public void getFrameworkStringValue() {
+        final BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
+        TypedValue value = new TypedValue();
+        while (state.keepRunning()) {
+            mRes.getValue(com.android.internal.R.string.cancel, value, false /* resolve_refs */);
+        }
+    }
+
+    @Test
+    public void getValueManyConfigurations() {
+        final BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
+        TypedValue value = new TypedValue();
+        while (state.keepRunning()) {
+            mRes.getValue(com.android.internal.R.string.mmcc_illegal_me, value,
+                    false /* resolve_refs */);
+        }
     }
 
     @Test
     public void getText() {
         final BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
         while (state.keepRunning()) {
-            mRes.getText(mTextId);
+            mRes.getText(R.string.long_text);
+        }
+    }
+
+
+    @Test
+    public void getFont() {
+        final BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
+        while (state.keepRunning()) {
+            mRes.getFont(R.font.samplefont);
+        }
+    }
+
+    @Test
+    public void getString() {
+        final BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
+        while (state.keepRunning()) {
+            mRes.getString(R.string.long_text);
+        }
+    }
+
+    @Test
+    public void getQuantityString() {
+        final BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
+        while (state.keepRunning()) {
+            mRes.getQuantityString(R.plurals.plurals_text, 5);
+        }
+    }
+
+    @Test
+    public void getQuantityText() {
+        final BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
+        while (state.keepRunning()) {
+            mRes.getQuantityText(R.plurals.plurals_text, 5);
+        }
+    }
+
+    @Test
+    public void getTextArray() {
+        final BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
+        while (state.keepRunning()) {
+            mRes.getTextArray(R.array.strings);
+        }
+    }
+
+    @Test
+    public void getStringArray() {
+        final BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
+        while (state.keepRunning()) {
+            mRes.getStringArray(R.array.strings);
+        }
+    }
+
+    @Test
+    public void getIntegerArray() {
+        final BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
+        while (state.keepRunning()) {
+            mRes.getIntArray(R.array.ints);
         }
     }
 
@@ -80,15 +170,23 @@
     public void getColor() {
         final BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
         while (state.keepRunning()) {
-            mRes.getColor(mColorId, null);
+            mRes.getColor(R.color.white, null);
         }
     }
 
     @Test
-    public void getInteger() {
+    public void getColorStateList() {
         final BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
         while (state.keepRunning()) {
-            mRes.getInteger(mIntegerId);
+            mRes.getColorStateList(R.color.color_state_list, null);
+        }
+    }
+
+    @Test
+    public void getVectorDrawable() {
+        final BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
+        while (state.keepRunning()) {
+            mRes.getDrawable(R.drawable.vector_drawable01, null);
         }
     }
 
@@ -96,7 +194,7 @@
     public void getLayoutAndTravese() {
         final BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
         while (state.keepRunning()) {
-            try (XmlResourceParser parser = mRes.getLayout(mLayoutId)) {
+            try (XmlResourceParser parser = mRes.getLayout(R.layout.test_relative_layout)) {
                 while (parser.next() != XmlPullParser.END_DOCUMENT) {
                     // Walk the entire tree
                 }
@@ -105,4 +203,23 @@
             }
         }
     }
-}
+
+    @Test
+    public void getLayoutAndTraverseInvalidateCaches() {
+        mRes.flushLayoutCache();
+        final BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
+        while (state.keepRunning()) {
+            try (XmlResourceParser parser = mRes.getLayout(R.layout.test_relative_layout)) {
+                while (parser.next() != XmlPullParser.END_DOCUMENT) {
+                    // Walk the entire tree
+                }
+            } catch (IOException | XmlPullParserException exception) {
+                fail("Parsing of the layout failed. Something is really broken");
+            }
+
+            state.pauseTiming();
+            mRes.flushLayoutCache();
+            state.resumeTiming();
+        }
+    }
+}
\ No newline at end of file
diff --git a/apct-tests/perftests/core/src/android/app/ResourcesThemePerfTest.java b/apct-tests/perftests/core/src/android/app/ResourcesThemePerfTest.java
index 1b07572..6123e69 100644
--- a/apct-tests/perftests/core/src/android/app/ResourcesThemePerfTest.java
+++ b/apct-tests/perftests/core/src/android/app/ResourcesThemePerfTest.java
@@ -16,13 +16,19 @@
 package android.app;
 
 import android.content.Context;
+import android.content.pm.ApplicationInfo;
+import android.content.pm.PackageManager;
+import android.content.res.Configuration;
 import android.content.res.Resources;
+import android.os.UserHandle;
 import android.perftests.utils.BenchmarkState;
 import android.perftests.utils.PerfStatusReporter;
+import android.view.Display;
 
 import androidx.test.InstrumentationRegistry;
 import androidx.test.filters.LargeTest;
 
+import org.junit.Assert;
 import org.junit.Before;
 import org.junit.Rule;
 import org.junit.Test;
@@ -35,13 +41,69 @@
     @Rule
     public PerfStatusReporter mPerfStatusReporter = new PerfStatusReporter();
 
+    private Context mContext;
+    private int mThemeResId;
     private Resources.Theme mTheme;
 
     @Before
-    public void setUp() {
-        Context context = InstrumentationRegistry.getTargetContext();
-        mTheme = context.getTheme();
+    public void setUp() throws Exception {
+        mContext = InstrumentationRegistry.getTargetContext();
+        mThemeResId = com.android.perftests.core.R.style.Base_V7_Theme_AppCompat;
+        mTheme = mContext.getResources().newTheme();
+        mTheme.applyStyle(mThemeResId, true /* force */);
+    }
 
+    @Test
+    public void applyStyle() {
+        Resources.Theme destTheme = mContext.getResources().newTheme();
+        final BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
+        while (state.keepRunning()) {
+            destTheme.applyStyle(mThemeResId, true /* force */);
+        }
+    }
+
+    @Test
+    public void rebase() {
+        Resources.Theme destTheme = mContext.getResources().newTheme();
+        destTheme.applyStyle(mThemeResId, true /* force */);
+        destTheme.applyStyle(android.R.style.Theme_Material, true /* force */);
+        final BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
+        while (state.keepRunning()) {
+            destTheme.rebase();
+        }
+    }
+
+    @Test
+    public void setToSameAssetManager() {
+        Resources.Theme destTheme = mContext.getResources().newTheme();
+        final BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
+        while (state.keepRunning()) {
+            destTheme.setTo(mTheme);
+        }
+    }
+
+    @Test
+    public void setToDifferentAssetManager() throws Exception {
+        // Create a new Resources object with the same asset paths but a different AssetManager
+        PackageManager packageManager = mContext.getApplicationContext().getPackageManager();
+        ApplicationInfo ai = packageManager.getApplicationInfo(mContext.getPackageName(),
+                UserHandle.myUserId());
+
+        ResourcesManager resourcesManager = ResourcesManager.getInstance();
+        Configuration c = resourcesManager.getConfiguration();
+        c.orientation = (c.orientation == Configuration.ORIENTATION_PORTRAIT)
+                ? Configuration.ORIENTATION_LANDSCAPE : Configuration.ORIENTATION_PORTRAIT;
+
+        Resources destResources = resourcesManager.getResources(null, ai.sourceDir,
+                ai.splitSourceDirs, ai.resourceDirs, ai.sharedLibraryFiles, Display.DEFAULT_DISPLAY,
+                c, mContext.getResources().getCompatibilityInfo(), null);
+        Assert.assertNotEquals(destResources.getAssets(), mContext.getAssets());
+
+        Resources.Theme destTheme = destResources.newTheme();
+        final BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
+        while (state.keepRunning()) {
+            destTheme.setTo(mTheme);
+        }
     }
 
     @Test
@@ -51,5 +113,4 @@
             mTheme.obtainStyledAttributes(android.R.style.Theme_Material, android.R.styleable.View);
         }
     }
-
-}
+}
\ No newline at end of file
diff --git a/apct-tests/perftests/utils/src/android/perftests/utils/TestPackageInstaller.java b/apct-tests/perftests/utils/src/android/perftests/utils/TestPackageInstaller.java
new file mode 100644
index 0000000..a433d80
--- /dev/null
+++ b/apct-tests/perftests/utils/src/android/perftests/utils/TestPackageInstaller.java
@@ -0,0 +1,145 @@
+/*
+ * 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 android.app.PendingIntent;
+import android.content.BroadcastReceiver;
+import android.content.Context;
+import android.content.Intent;
+import android.content.IntentFilter;
+import android.content.IntentSender;
+import android.content.pm.PackageInstaller;
+import android.content.res.Resources;
+import android.util.Log;
+
+import org.junit.Assert;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.util.concurrent.BlockingQueue;
+import java.util.concurrent.LinkedBlockingQueue;
+
+/**
+ * Installs packages included within the assets directory.
+ */
+public class TestPackageInstaller {
+    private static final String LOG_TAG = "TestPackageInstaller";
+    private static final String BROADCAST_ACTION =
+            "com.android.perftests.core.ACTION_INSTALL_COMMIT";
+
+    private final Context mContext;
+    public TestPackageInstaller(Context context) {
+        mContext = context;
+    }
+
+
+
+    /**
+     * Installs an APK located at the specified path in the assets directory.
+     **/
+    public InstalledPackage installPackage(String resourceName) throws IOException,
+            InterruptedException {
+        Log.d(LOG_TAG, "Installing resource APK '" + resourceName + "'");
+        LocalBroadcastReceiver intentSender = new LocalBroadcastReceiver(mContext);
+
+        // Initialize the package install session.
+        PackageInstaller packageInstaller = mContext.getPackageManager().getPackageInstaller();
+        PackageInstaller.SessionParams params = new PackageInstaller.SessionParams(
+                PackageInstaller.SessionParams.MODE_FULL_INSTALL);
+        params.setInstallAsInstantApp(false);
+        int sessionId = packageInstaller.createSession(params);
+        PackageInstaller.Session session = packageInstaller.openSession(sessionId);
+
+        // Copy the apk to the install session.
+        try (OutputStream os = session.openWrite("TestPackageInstaller", 0, -1);
+             InputStream is = mContext.getResources().getAssets().openNonAsset(resourceName)) {
+            if (is == null) {
+                throw new IOException("Resource " + resourceName + " not found");
+            }
+            byte[] buffer = new byte[4096];
+            int n;
+            while ((n = is.read(buffer)) >= 0) {
+                os.write(buffer, 0, n);
+            }
+        }
+
+        session.commit(intentSender.getIntentSender(sessionId));
+        session.close();
+
+        // Retrieve the results of the installation.
+        Intent intent = intentSender.getIntentSenderResult();
+        int status = intent.getIntExtra(PackageInstaller.EXTRA_STATUS,
+                PackageInstaller.STATUS_FAILURE);
+        Assert.assertEquals(PackageInstaller.STATUS_SUCCESS, status);
+        String packageName = intent.getStringExtra(PackageInstaller.EXTRA_PACKAGE_NAME);
+        return new InstalledPackage(sessionId, packageName);
+    }
+
+    public class InstalledPackage {
+        private int mSessionId;
+        private String mPackageName;
+
+        private InstalledPackage(int sessionId, String packageName) {
+            mSessionId = sessionId;
+            mPackageName = packageName;
+        }
+
+        public String getPackageName() {
+            return mPackageName;
+        }
+
+        public void uninstall() throws Exception {
+            Log.d(LOG_TAG, "Uninstalling package '" + mPackageName + "'");
+            LocalBroadcastReceiver intentSender = new LocalBroadcastReceiver(mContext);
+            PackageInstaller packageInstaller = mContext.getPackageManager().getPackageInstaller();
+            packageInstaller.uninstall(mPackageName, intentSender.getIntentSender(mSessionId));
+            int status = intentSender.getIntentSenderResult()
+                    .getIntExtra(PackageInstaller.EXTRA_STATUS, PackageInstaller.STATUS_FAILURE);
+            Assert.assertEquals(PackageInstaller.STATUS_SUCCESS, status);
+        }
+    }
+
+    private class LocalBroadcastReceiver extends BroadcastReceiver {
+        private final BlockingQueue<Intent> mIntentSenderResults = new LinkedBlockingQueue<>();
+        private final Context mContext;
+
+        private LocalBroadcastReceiver(Context context) {
+            mContext = context;
+        }
+
+        @Override
+        public void onReceive(Context context, Intent intent) {
+            mIntentSenderResults.add(intent);
+        }
+
+        IntentSender getIntentSender(int sessionId) {
+            String action = BROADCAST_ACTION + "." + sessionId;
+            IntentFilter filter = new IntentFilter(action);
+            mContext.registerReceiver(this, filter);
+
+            Intent intent = new Intent(action);
+            PendingIntent pending = PendingIntent.getBroadcast(mContext, sessionId, intent,
+                    PendingIntent.FLAG_UPDATE_CURRENT);
+            return pending.getIntentSender();
+        }
+
+        Intent getIntentSenderResult() throws InterruptedException {
+            return mIntentSenderResults.take();
+        }
+    }
+}
diff --git a/apex/jobscheduler/framework/java/android/app/DeviceIdleFrameworkInitializer.java b/apex/jobscheduler/framework/java/android/app/DeviceIdleFrameworkInitializer.java
index a807eb1..5b14056 100644
--- a/apex/jobscheduler/framework/java/android/app/DeviceIdleFrameworkInitializer.java
+++ b/apex/jobscheduler/framework/java/android/app/DeviceIdleFrameworkInitializer.java
@@ -36,7 +36,7 @@
         SystemServiceRegistry.registerCachedService(
                 Context.DEVICE_IDLE_CONTROLLER, DeviceIdleManager.class,
                 (context, b) -> new DeviceIdleManager(
-                        context.getOuterContext(), IDeviceIdleController.Stub.asInterface(b)));
+                        context, IDeviceIdleController.Stub.asInterface(b)));
         PowerManager.setIsIgnoringBatteryOptimizationsCallback((packageName) -> {
             // No need for synchronization on sIDeviceIdleController; worst case
             // we just initialize it twice.
diff --git a/apex/jobscheduler/framework/java/android/os/DeviceIdleManager.java b/apex/jobscheduler/framework/java/android/os/DeviceIdleManager.java
index 9039f92..e27670c 100644
--- a/apex/jobscheduler/framework/java/android/os/DeviceIdleManager.java
+++ b/apex/jobscheduler/framework/java/android/os/DeviceIdleManager.java
@@ -17,10 +17,13 @@
 package android.os;
 
 import android.annotation.NonNull;
+import android.annotation.RequiresPermission;
 import android.annotation.SystemService;
 import android.annotation.TestApi;
 import android.content.Context;
 
+import java.util.List;
+
 /**
  * Access to the service that keeps track of device idleness and drives low power mode based on
  * that.
@@ -66,4 +69,19 @@
             return new String[0];
         }
     }
+
+    /**
+     * Add the specified packages to the power save whitelist.
+     *
+     * @return the number of packages that were successfully added to the whitelist
+     */
+    @RequiresPermission(android.Manifest.permission.DEVICE_POWER)
+    public int addPowerSaveWhitelistApps(@NonNull List<String> packageNames) {
+        try {
+            return mService.addPowerSaveWhitelistApps(packageNames);
+        } catch (RemoteException e) {
+            e.rethrowFromSystemServer();
+            return 0;
+        }
+    }
 }
diff --git a/apex/jobscheduler/framework/java/android/os/IDeviceIdleController.aidl b/apex/jobscheduler/framework/java/android/os/IDeviceIdleController.aidl
index 9d5becb..20fb000 100644
--- a/apex/jobscheduler/framework/java/android/os/IDeviceIdleController.aidl
+++ b/apex/jobscheduler/framework/java/android/os/IDeviceIdleController.aidl
@@ -21,6 +21,7 @@
 /** @hide */
 interface IDeviceIdleController {
     void addPowerSaveWhitelistApp(String name);
+    int addPowerSaveWhitelistApps(in List<String> packageNames);
     void removePowerSaveWhitelistApp(String name);
     /* Removes an app from the system whitelist. Calling restoreSystemPowerWhitelistApp will add
     the app back into the system whitelist */
diff --git a/apex/jobscheduler/framework/java/com/android/server/DeviceIdleInternal.java b/apex/jobscheduler/framework/java/com/android/server/DeviceIdleInternal.java
index 1273249..6475f57 100644
--- a/apex/jobscheduler/framework/java/com/android/server/DeviceIdleInternal.java
+++ b/apex/jobscheduler/framework/java/com/android/server/DeviceIdleInternal.java
@@ -49,4 +49,24 @@
     int[] getPowerSaveWhitelistUserAppIds();
 
     int[] getPowerSaveTempWhitelistAppIds();
+
+    /**
+     * Listener to be notified when DeviceIdleController determines that the device has moved or is
+     * stationary.
+     */
+    interface StationaryListener {
+        void onDeviceStationaryChanged(boolean isStationary);
+    }
+
+    /**
+     * Registers a listener that will be notified when the system has detected that the device is
+     * stationary or in motion.
+     */
+    void registerStationaryListener(StationaryListener listener);
+
+    /**
+     * Unregisters a registered stationary listener from being notified when the system has detected
+     * that the device is stationary or in motion.
+     */
+    void unregisterStationaryListener(StationaryListener listener);
 }
diff --git a/apex/jobscheduler/framework/java/com/android/server/usage/AppStandbyInternal.java b/apex/jobscheduler/framework/java/com/android/server/usage/AppStandbyInternal.java
new file mode 100644
index 0000000..3cfb080
--- /dev/null
+++ b/apex/jobscheduler/framework/java/com/android/server/usage/AppStandbyInternal.java
@@ -0,0 +1,112 @@
+package com.android.server.usage;
+
+import android.app.usage.AppStandbyInfo;
+import android.app.usage.UsageEvents;
+import android.app.usage.UsageStatsManager.StandbyBuckets;
+import android.app.usage.UsageStatsManagerInternal.AppIdleStateChangeListener;
+import android.content.Context;
+import android.os.Looper;
+
+import com.android.internal.util.IndentingPrintWriter;
+
+import java.io.PrintWriter;
+import java.lang.reflect.Constructor;
+import java.lang.reflect.InvocationTargetException;
+import java.util.List;
+import java.util.Set;
+
+public interface AppStandbyInternal {
+    /**
+     * TODO AppStandbyController should probably be a binder service, and then we shouldn't need
+     * this method.
+     */
+    static AppStandbyInternal newAppStandbyController(ClassLoader loader, Context context,
+            Looper looper) {
+        try {
+            final Class<?> clazz = Class.forName("com.android.server.usage.AppStandbyController",
+                    true, loader);
+            final Constructor<?> ctor =  clazz.getConstructor(Context.class, Looper.class);
+            return (AppStandbyInternal) ctor.newInstance(context, looper);
+        } catch (NoSuchMethodException | InstantiationException
+                | IllegalAccessException | InvocationTargetException | ClassNotFoundException e) {
+            throw new RuntimeException("Unable to instantiate AppStandbyController!", e);
+        }
+    }
+
+    void onBootPhase(int phase);
+
+    boolean isParoledOrCharging();
+
+    void postCheckIdleStates(int userId);
+
+    /**
+     * We send a different message to check idle states once, otherwise we would end up
+     * scheduling a series of repeating checkIdleStates each time we fired off one.
+     */
+    void postOneTimeCheckIdleStates();
+
+    void reportEvent(UsageEvents.Event event, long elapsedRealtime, int userId);
+
+    void setLastJobRunTime(String packageName, int userId, long elapsedRealtime);
+
+    long getTimeSinceLastJobRun(String packageName, int userId);
+
+    void onUserRemoved(int userId);
+
+    void addListener(AppIdleStateChangeListener listener);
+
+    void removeListener(AppIdleStateChangeListener listener);
+
+    int getAppId(String packageName);
+
+    boolean isAppIdleFilteredOrParoled(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,
+            long elapsedRealtime);
+
+    int[] getIdleUidsForUser(int userId);
+
+    void setAppIdleAsync(String packageName, boolean idle, int userId);
+
+    @StandbyBuckets
+    int getAppStandbyBucket(String packageName, int userId,
+            long elapsedRealtime, boolean shouldObfuscateInstantApps);
+
+    List<AppStandbyInfo> getAppStandbyBuckets(int userId);
+
+    void setAppStandbyBucket(String packageName, int userId, @StandbyBuckets int newBucket,
+            int reason, long elapsedRealtime, boolean resetTimeout);
+
+    void addActiveDeviceAdmin(String adminPkg, int userId);
+
+    void setActiveAdminApps(Set<String> adminPkgs, int userId);
+
+    void onAdminDataAvailable();
+
+    void clearCarrierPrivilegedApps();
+
+    void flushToDisk(int userId);
+
+    void flushDurationsToDisk();
+
+    void initializeDefaultsForSystemApps(int userId);
+
+    void postReportContentProviderUsage(String name, String packageName, int userId);
+
+    void postReportSyncScheduled(String packageName, int userId, boolean exempted);
+
+    void postReportExemptedSyncStart(String packageName, int userId);
+
+    void dumpUser(IndentingPrintWriter idpw, int userId, String pkg);
+
+    void dumpState(String[] args, PrintWriter pw);
+
+    boolean isAppIdleEnabled();
+}
diff --git a/apex/jobscheduler/service/java/com/android/server/DeviceIdleController.java b/apex/jobscheduler/service/java/com/android/server/DeviceIdleController.java
index 65aaf20..4ee46f4 100644
--- a/apex/jobscheduler/service/java/com/android/server/DeviceIdleController.java
+++ b/apex/jobscheduler/service/java/com/android/server/DeviceIdleController.java
@@ -48,7 +48,6 @@
 import android.os.Binder;
 import android.os.Bundle;
 import android.os.Environment;
-import android.os.FileUtils;
 import android.os.Handler;
 import android.os.IDeviceIdleController;
 import android.os.Looper;
@@ -106,6 +105,8 @@
 import java.io.PrintWriter;
 import java.nio.charset.StandardCharsets;
 import java.util.Arrays;
+import java.util.Collections;
+import java.util.List;
 import java.util.stream.Collectors;
 
 /**
@@ -275,6 +276,7 @@
     private IBatteryStats mBatteryStats;
     private ActivityManagerInternal mLocalActivityManager;
     private ActivityTaskManagerInternal mLocalActivityTaskManager;
+    private DeviceIdleInternal mLocalService;
     private PowerManagerInternal mLocalPowerManager;
     private PowerManager mPowerManager;
     private INetworkPolicyManager mNetworkPolicyManager;
@@ -289,6 +291,7 @@
     private boolean mLightEnabled;
     private boolean mDeepEnabled;
     private boolean mQuickDozeActivated;
+    private boolean mQuickDozeActivatedWhileIdling;
     private boolean mForceIdle;
     private boolean mNetworkConnected;
     private boolean mScreenOn;
@@ -300,6 +303,10 @@
     private boolean mHasNetworkLocation;
     private Location mLastGenericLocation;
     private Location mLastGpsLocation;
+
+    /** Time in the elapsed realtime timebase when this listener last received a motion event. */
+    private long mLastMotionEventElapsed;
+
     // Current locked state of the screen
     private boolean mScreenLocked;
     private int mNumBlockingConstraints = 0;
@@ -549,6 +556,9 @@
      */
     private ArrayMap<String, Integer> mRemovedFromSystemWhitelistApps = new ArrayMap<>();
 
+    private final ArraySet<DeviceIdleInternal.StationaryListener> mStationaryListeners =
+            new ArraySet<>();
+
     private static final int EVENT_NULL = 0;
     private static final int EVENT_NORMAL = 1;
     private static final int EVENT_LIGHT_IDLE = 2;
@@ -607,6 +617,22 @@
         }
     };
 
+
+    private final AlarmManager.OnAlarmListener mMotionTimeoutAlarmListener = () -> {
+        synchronized (DeviceIdleController.this) {
+            if (!isStationaryLocked()) {
+                // If the device keeps registering motion, then the alarm should be
+                // rescheduled, so this shouldn't go off until the device is stationary.
+                // This case may happen in a race condition (alarm goes off right before
+                // motion is detected, but handleMotionDetectedLocked is called before
+                // we enter this block).
+                Slog.w(TAG, "motion timeout went off and device isn't stationary");
+                return;
+            }
+        }
+        postStationaryStatusUpdated();
+    };
+
     private final AlarmManager.OnAlarmListener mSensingTimeoutAlarmListener
             = new AlarmManager.OnAlarmListener() {
         @Override
@@ -656,12 +682,70 @@
         }
     };
 
+    /** Post stationary status only to this listener. */
+    private void postStationaryStatus(DeviceIdleInternal.StationaryListener listener) {
+        mHandler.obtainMessage(MSG_REPORT_STATIONARY_STATUS, listener).sendToTarget();
+    }
+
+    /** Post stationary status to all registered listeners. */
+    private void postStationaryStatusUpdated() {
+        mHandler.sendEmptyMessage(MSG_REPORT_STATIONARY_STATUS);
+    }
+
+    private boolean isStationaryLocked() {
+        final long now = mInjector.getElapsedRealtime();
+        return mMotionListener.active
+                // Listening for motion for long enough and last motion was long enough ago.
+                && now - Math.max(mMotionListener.activatedTimeElapsed, mLastMotionEventElapsed)
+                        >= mConstants.MOTION_INACTIVE_TIMEOUT;
+    }
+
+    @VisibleForTesting
+    void registerStationaryListener(DeviceIdleInternal.StationaryListener listener) {
+        synchronized (this) {
+            if (!mStationaryListeners.add(listener)) {
+                // Listener already registered.
+                return;
+            }
+            postStationaryStatus(listener);
+            if (mMotionListener.active) {
+                if (!isStationaryLocked() && mStationaryListeners.size() == 1) {
+                    // First listener to be registered and the device isn't stationary, so we
+                    // need to register the alarm to report the device is stationary.
+                    scheduleMotionTimeoutAlarmLocked();
+                }
+            } else {
+                startMonitoringMotionLocked();
+                scheduleMotionTimeoutAlarmLocked();
+            }
+        }
+    }
+
+    private void unregisterStationaryListener(DeviceIdleInternal.StationaryListener listener) {
+        synchronized (this) {
+            if (mStationaryListeners.remove(listener) && mStationaryListeners.size() == 0
+                    // Motion detection is started when transitioning from INACTIVE to IDLE_PENDING
+                    // and so doesn't need to be on for ACTIVE or INACTIVE states.
+                    // Motion detection isn't needed when idling due to Quick Doze.
+                    && (mState == STATE_ACTIVE || mState == STATE_INACTIVE
+                            || mQuickDozeActivated)) {
+                maybeStopMonitoringMotionLocked();
+            }
+        }
+    }
+
     @VisibleForTesting
     final class MotionListener extends TriggerEventListener
             implements SensorEventListener {
 
         boolean active = false;
 
+        /**
+         * Time in the elapsed realtime timebase when this listener was activated. Only valid if
+         * {@link #active} is true.
+         */
+        long activatedTimeElapsed;
+
         public boolean isActive() {
             return active;
         }
@@ -669,7 +753,6 @@
         @Override
         public void onTrigger(TriggerEvent event) {
             synchronized (DeviceIdleController.this) {
-                active = false;
                 motionLocked();
             }
         }
@@ -677,8 +760,6 @@
         @Override
         public void onSensorChanged(SensorEvent event) {
             synchronized (DeviceIdleController.this) {
-                mSensorManager.unregisterListener(this, mMotionSensor);
-                active = false;
                 motionLocked();
             }
         }
@@ -696,6 +777,7 @@
             }
             if (success) {
                 active = true;
+                activatedTimeElapsed = mInjector.getElapsedRealtime();
             } else {
                 Slog.e(TAG, "Unable to register for " + mMotionSensor);
             }
@@ -1303,6 +1385,8 @@
     private static final int MSG_REPORT_IDLE_OFF = 4;
     private static final int MSG_REPORT_ACTIVE = 5;
     private static final int MSG_TEMP_APP_WHITELIST_TIMEOUT = 6;
+    @VisibleForTesting
+    static final int MSG_REPORT_STATIONARY_STATUS = 7;
     private static final int MSG_FINISH_IDLE_OP = 8;
     private static final int MSG_REPORT_TEMP_APP_WHITELIST_CHANGED = 9;
     private static final int MSG_SEND_CONSTRAINT_MONITORING = 10;
@@ -1428,6 +1512,32 @@
                     updatePreIdleFactor();
                     maybeDoImmediateMaintenance();
                 } break;
+                case MSG_REPORT_STATIONARY_STATUS: {
+                    final DeviceIdleInternal.StationaryListener newListener =
+                            (DeviceIdleInternal.StationaryListener) msg.obj;
+                    final DeviceIdleInternal.StationaryListener[] listeners;
+                    final boolean isStationary;
+                    synchronized (DeviceIdleController.this) {
+                        isStationary = isStationaryLocked();
+                        if (newListener == null) {
+                            // Only notify all listeners if we aren't directing to one listener.
+                            listeners = mStationaryListeners.toArray(
+                                    new DeviceIdleInternal.StationaryListener[
+                                            mStationaryListeners.size()]);
+                        } else {
+                            listeners = null;
+                        }
+                    }
+                    if (listeners != null) {
+                        for (DeviceIdleInternal.StationaryListener listener : listeners) {
+                            listener.onDeviceStationaryChanged(isStationary);
+                        }
+                    }
+                    if (newListener != null) {
+                        newListener.onDeviceStationaryChanged(isStationary);
+                    }
+                }
+                break;
             }
         }
     }
@@ -1441,11 +1551,20 @@
             if (DEBUG) {
                 Slog.i(TAG, "addPowerSaveWhitelistApp(name = " + name + ")");
             }
+            addPowerSaveWhitelistApps(Collections.singletonList(name));
+        }
+
+        @Override
+        public int addPowerSaveWhitelistApps(List<String> packageNames) {
+            if (DEBUG) {
+                Slog.i(TAG,
+                        "addPowerSaveWhitelistApps(name = " + packageNames + ")");
+            }
             getContext().enforceCallingOrSelfPermission(android.Manifest.permission.DEVICE_POWER,
                     null);
             long ident = Binder.clearCallingIdentity();
             try {
-                addPowerSaveWhitelistAppInternal(name);
+                return addPowerSaveWhitelistAppsInternal(packageNames);
             } finally {
                 Binder.restoreCallingIdentity(ident);
             }
@@ -1680,11 +1799,21 @@
         public int[] getPowerSaveTempWhitelistAppIds() {
             return DeviceIdleController.this.getAppIdTempWhitelistInternal();
         }
+
+        @Override
+        public void registerStationaryListener(StationaryListener listener) {
+            DeviceIdleController.this.registerStationaryListener(listener);
+        }
+
+        @Override
+        public void unregisterStationaryListener(StationaryListener listener) {
+            DeviceIdleController.this.unregisterStationaryListener(listener);
+        }
     }
 
     static class Injector {
         private final Context mContext;
-        private ConnectivityService mConnectivityService;
+        private ConnectivityManager mConnectivityManager;
         private Constants mConstants;
         private LocationManager mLocationManager;
 
@@ -1705,12 +1834,11 @@
             return new AppStateTracker(ctx, looper);
         }
 
-        ConnectivityService getConnectivityService() {
-            if (mConnectivityService == null) {
-                mConnectivityService = (ConnectivityService) ServiceManager.getService(
-                        Context.CONNECTIVITY_SERVICE);
+        ConnectivityManager getConnectivityManager() {
+            if (mConnectivityManager == null) {
+                mConnectivityManager = mContext.getSystemService(ConnectivityManager.class);
             }
-            return mConnectivityService;
+            return mConnectivityManager;
         }
 
         Constants getConstants(DeviceIdleController controller, Handler handler,
@@ -1864,7 +1992,8 @@
 
         mBinderService = new BinderService();
         publishBinderService(Context.DEVICE_IDLE_CONTROLLER, mBinderService);
-        publishLocalService(DeviceIdleInternal.class, new LocalService());
+        mLocalService = new LocalService();
+        publishLocalService(DeviceIdleInternal.class, mLocalService);
     }
 
     @Override
@@ -1909,7 +2038,7 @@
 
                 if (getContext().getResources().getBoolean(
                         com.android.internal.R.bool.config_autoPowerModePrefetchLocation)) {
-                    mLocationRequest = new LocationRequest()
+                    mLocationRequest = LocationRequest.create()
                         .setQuality(LocationRequest.ACCURACY_FINE)
                         .setInterval(0)
                         .setFastestInterval(0)
@@ -2070,21 +2199,35 @@
         }
     }
 
-    public boolean addPowerSaveWhitelistAppInternal(String name) {
+    private int addPowerSaveWhitelistAppsInternal(List<String> pkgNames) {
+        int numAdded = 0;
+        int numErrors = 0;
         synchronized (this) {
-            try {
-                ApplicationInfo ai = getContext().getPackageManager().getApplicationInfo(name,
-                        PackageManager.MATCH_ANY_USER);
-                if (mPowerSaveWhitelistUserApps.put(name, UserHandle.getAppId(ai.uid)) == null) {
-                    reportPowerSaveWhitelistChangedLocked();
-                    updateWhitelistAppIdsLocked();
-                    writeConfigFileLocked();
+            for (int i = pkgNames.size() - 1; i >= 0; --i) {
+                final String name = pkgNames.get(i);
+                if (name == null) {
+                    numErrors++;
+                    continue;
                 }
-                return true;
-            } catch (PackageManager.NameNotFoundException e) {
-                return false;
+                try {
+                    ApplicationInfo ai = getContext().getPackageManager().getApplicationInfo(name,
+                            PackageManager.MATCH_ANY_USER);
+                    if (mPowerSaveWhitelistUserApps.put(name, UserHandle.getAppId(ai.uid))
+                            == null) {
+                        numAdded++;
+                    }
+                } catch (PackageManager.NameNotFoundException e) {
+                    Slog.e(TAG, "Tried to add unknown package to power save whitelist: " + name);
+                    numErrors++;
+                }
+            }
+            if (numAdded > 0) {
+                reportPowerSaveWhitelistChangedLocked();
+                updateWhitelistAppIdsLocked();
+                writeConfigFileLocked();
             }
         }
+        return pkgNames.size() - numErrors;
     }
 
     public boolean removePowerSaveWhitelistAppInternal(String name) {
@@ -2497,9 +2640,9 @@
     }
 
     void updateConnectivityState(Intent connIntent) {
-        ConnectivityService cm;
+        ConnectivityManager cm;
         synchronized (this) {
-            cm = mInjector.getConnectivityService();
+            cm = mInjector.getConnectivityManager();
         }
         if (cm == null) {
             return;
@@ -2595,6 +2738,8 @@
     void updateQuickDozeFlagLocked(boolean enabled) {
         if (DEBUG) Slog.i(TAG, "updateQuickDozeFlagLocked: enabled=" + enabled);
         mQuickDozeActivated = enabled;
+        mQuickDozeActivatedWhileIdling =
+                mQuickDozeActivated && (mState == STATE_IDLE || mState == STATE_IDLE_MAINTENANCE);
         if (enabled) {
             // If Quick Doze is enabled, see if we should go straight into it.
             becomeInactiveIfAppropriateLocked();
@@ -2779,10 +2924,11 @@
         mNextIdlePendingDelay = 0;
         mNextIdleDelay = 0;
         mIdleStartTime = 0;
+        mQuickDozeActivatedWhileIdling = false;
         cancelAlarmLocked();
         cancelSensingTimeoutAlarmLocked();
         cancelLocatingLocked();
-        stopMonitoringMotionLocked();
+        maybeStopMonitoringMotionLocked();
         mAnyMotionDetector.stop();
         updateActiveConstraintsLocked();
     }
@@ -3269,11 +3415,23 @@
 
     void motionLocked() {
         if (DEBUG) Slog.d(TAG, "motionLocked()");
-        // The motion sensor will have been disabled at this point
+        mLastMotionEventElapsed = mInjector.getElapsedRealtime();
         handleMotionDetectedLocked(mConstants.MOTION_INACTIVE_TIMEOUT, "motion");
     }
 
     void handleMotionDetectedLocked(long timeout, String type) {
+        if (mStationaryListeners.size() > 0) {
+            postStationaryStatusUpdated();
+            scheduleMotionTimeoutAlarmLocked();
+        }
+        if (mQuickDozeActivated && !mQuickDozeActivatedWhileIdling) {
+            // Don't exit idle due to motion if quick doze is enabled.
+            // However, if the device started idling due to the normal progression (going through
+            // all the states) and then had quick doze activated, come out briefly on motion so the
+            // user can get slightly fresher content.
+            return;
+        }
+        maybeStopMonitoringMotionLocked();
         // The device is not yet active, so we want to go back to the pending idle
         // state to wait again for no motion.  Note that we only monitor for motion
         // after moving out of the inactive state, so no need to worry about that.
@@ -3325,10 +3483,15 @@
         }
     }
 
-    void stopMonitoringMotionLocked() {
-        if (DEBUG) Slog.d(TAG, "stopMonitoringMotionLocked()");
-        if (mMotionSensor != null && mMotionListener.active) {
+    /**
+     * Stops motion monitoring. Will not stop monitoring if there are registered stationary
+     * listeners.
+     */
+    private void maybeStopMonitoringMotionLocked() {
+        if (DEBUG) Slog.d(TAG, "maybeStopMonitoringMotionLocked()");
+        if (mMotionSensor != null && mMotionListener.active && mStationaryListeners.size() == 0) {
             mMotionListener.unregisterLocked();
+            cancelMotionTimeoutAlarmLocked();
         }
     }
 
@@ -3355,6 +3518,10 @@
         }
     }
 
+    private void cancelMotionTimeoutAlarmLocked() {
+        mAlarmManager.cancel(mMotionTimeoutAlarmListener);
+    }
+
     void cancelSensingTimeoutAlarmLocked() {
         if (mNextSensingTimeoutAlarmTime != 0) {
             mNextSensingTimeoutAlarmTime = 0;
@@ -3395,6 +3562,14 @@
                 mNextLightAlarmTime, "DeviceIdleController.light", mLightAlarmListener, mHandler);
     }
 
+    private void scheduleMotionTimeoutAlarmLocked() {
+        if (DEBUG) Slog.d(TAG, "scheduleMotionAlarmLocked");
+        long nextMotionTimeoutAlarmTime =
+                mInjector.getElapsedRealtime() + mConstants.MOTION_INACTIVE_TIMEOUT;
+        mAlarmManager.set(AlarmManager.ELAPSED_REALTIME_WAKEUP, nextMotionTimeoutAlarmTime,
+                "DeviceIdleController.motion", mMotionTimeoutAlarmListener, mHandler);
+    }
+
     void scheduleSensingTimeoutAlarmLocked(long delay) {
         if (DEBUG) Slog.d(TAG, "scheduleSensingAlarmLocked(" + delay + ")");
         mNextSensingTimeoutAlarmTime = SystemClock.elapsedRealtime() + delay;
@@ -3598,9 +3773,6 @@
             try {
                 stream = mConfigFile.startWrite();
                 memStream.writeTo(stream);
-                stream.flush();
-                FileUtils.sync(stream);
-                stream.close();
                 mConfigFile.finishWrite(stream);
             } catch (IOException e) {
                 Slog.w(TAG, "Error writing config file", e);
@@ -3923,7 +4095,8 @@
                         char op = arg.charAt(0);
                         String pkg = arg.substring(1);
                         if (op == '+') {
-                            if (addPowerSaveWhitelistAppInternal(pkg)) {
+                            if (addPowerSaveWhitelistAppsInternal(Collections.singletonList(pkg))
+                                    == 1) {
                                 pw.println("Added: " + pkg);
                             } else {
                                 pw.println("Unknown package: " + pkg);
@@ -4315,9 +4488,14 @@
                 }
                 pw.println("  }");
             }
-            if (mUseMotionSensor) {
+            if (mUseMotionSensor || mStationaryListeners.size() > 0) {
                 pw.print("  mMotionActive="); pw.println(mMotionListener.active);
                 pw.print("  mNotMoving="); pw.println(mNotMoving);
+                pw.print("  mMotionListener.activatedTimeElapsed=");
+                pw.println(mMotionListener.activatedTimeElapsed);
+                pw.print("  mLastMotionEventElapsed="); pw.println(mLastMotionEventElapsed);
+                pw.print("  "); pw.print(mStationaryListeners.size());
+                pw.println(" stationary listeners registered");
             }
             pw.print("  mLocating="); pw.print(mLocating); pw.print(" mHasGps=");
                     pw.print(mHasGps); pw.print(" mHasNetwork=");
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 329d4b7..14d5a68 100644
--- a/apex/jobscheduler/service/java/com/android/server/job/JobSchedulerService.java
+++ b/apex/jobscheduler/service/java/com/android/server/job/JobSchedulerService.java
@@ -109,6 +109,9 @@
 import java.io.FileDescriptor;
 import java.io.PrintWriter;
 import java.time.Clock;
+import java.time.Instant;
+import java.time.ZoneId;
+import java.time.ZoneOffset;
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.Collections;
@@ -144,10 +147,53 @@
 
     @VisibleForTesting
     public static Clock sSystemClock = Clock.systemUTC();
+
+    private abstract static class MySimpleClock extends Clock {
+        private final ZoneId mZoneId;
+
+        MySimpleClock(ZoneId zoneId) {
+            this.mZoneId = zoneId;
+        }
+
+        @Override
+        public ZoneId getZone() {
+            return mZoneId;
+        }
+
+        @Override
+        public Clock withZone(ZoneId zone) {
+            return new MySimpleClock(zone) {
+                @Override
+                public long millis() {
+                    return MySimpleClock.this.millis();
+                }
+            };
+        }
+
+        @Override
+        public abstract long millis();
+
+        @Override
+        public Instant instant() {
+            return Instant.ofEpochMilli(millis());
+        }
+    }
+
     @VisibleForTesting
-    public static Clock sUptimeMillisClock = SystemClock.uptimeClock();
+    public static Clock sUptimeMillisClock = new MySimpleClock(ZoneOffset.UTC) {
+        @Override
+        public long millis() {
+            return SystemClock.uptimeMillis();
+        }
+    };
+
     @VisibleForTesting
-    public static Clock sElapsedRealtimeClock = SystemClock.elapsedRealtimeClock();
+    public static Clock sElapsedRealtimeClock =  new MySimpleClock(ZoneOffset.UTC) {
+        @Override
+        public long millis() {
+            return SystemClock.elapsedRealtime();
+        }
+    };
 
     /** Global local for all job scheduler state. */
     final Object mLock = new Object();
@@ -979,17 +1025,18 @@
             // This may throw a SecurityException.
             jobStatus.prepareLocked();
 
-            if (work != null) {
-                // If work has been supplied, enqueue it into the new job.
-                jobStatus.enqueueWorkLocked(work);
-            }
-
             if (toCancel != null) {
                 // Implicitly replaces the existing job record with the new instance
                 cancelJobImplLocked(toCancel, jobStatus, "job rescheduled by app");
             } else {
                 startTrackingJobLocked(jobStatus, null);
             }
+
+            if (work != null) {
+                // If work has been supplied, enqueue it into the new job.
+                jobStatus.enqueueWorkLocked(work);
+            }
+
             StatsLog.write_non_chained(StatsLog.SCHEDULED_JOB_STATE_CHANGED,
                     uId, null, jobStatus.getBatteryName(),
                     StatsLog.SCHEDULED_JOB_STATE_CHANGED__STATE__SCHEDULED,
@@ -2126,7 +2173,7 @@
                     job.getServiceComponent(), PackageManager.MATCH_DEBUG_TRIAGED_MISSING,
                     job.getUserId());
         } catch (RemoteException e) {
-            throw e.rethrowAsRuntimeException();
+            throw new RuntimeException(e);
         }
 
         if (service == null) {
diff --git a/apex/jobscheduler/service/java/com/android/server/job/JobServiceContext.java b/apex/jobscheduler/service/java/com/android/server/job/JobServiceContext.java
index 782e646..26db4a3 100644
--- a/apex/jobscheduler/service/java/com/android/server/job/JobServiceContext.java
+++ b/apex/jobscheduler/service/java/com/android/server/job/JobServiceContext.java
@@ -251,7 +251,7 @@
                 binding = mContext.bindServiceAsUser(intent, this,
                         Context.BIND_AUTO_CREATE | Context.BIND_NOT_FOREGROUND
                         | Context.BIND_NOT_PERCEPTIBLE,
-                        new UserHandle(job.getUserId()));
+                        UserHandle.of(job.getUserId()));
             } catch (SecurityException e) {
                 // Some permission policy, for example INTERACT_ACROSS_USERS and
                 // android:singleUser, can result in a SecurityException being thrown from
diff --git a/apex/jobscheduler/service/java/com/android/server/job/controllers/ConnectivityController.java b/apex/jobscheduler/service/java/com/android/server/job/controllers/ConnectivityController.java
index 43e8dfb..7d36303 100644
--- a/apex/jobscheduler/service/java/com/android/server/job/controllers/ConnectivityController.java
+++ b/apex/jobscheduler/service/java/com/android/server/job/controllers/ConnectivityController.java
@@ -34,6 +34,7 @@
 import android.os.Message;
 import android.os.UserHandle;
 import android.text.format.DateUtils;
+import android.util.ArrayMap;
 import android.util.ArraySet;
 import android.util.DataUnit;
 import android.util.Log;
@@ -441,7 +442,7 @@
         synchronized (mLock) {
             // Since this is a really hot codepath, temporarily cache any
             // answers that we get from ConnectivityManager.
-            final SparseArray<NetworkCapabilities> networkToCapabilities = new SparseArray<>();
+            final ArrayMap<Network, NetworkCapabilities> networkToCapabilities = new ArrayMap<>();
 
             boolean changed = false;
             if (filterUid == -1) {
@@ -460,17 +461,16 @@
     }
 
     private boolean updateTrackedJobsLocked(ArraySet<JobStatus> jobs, Network filterNetwork,
-            SparseArray<NetworkCapabilities> networkToCapabilities) {
+            ArrayMap<Network, NetworkCapabilities> networkToCapabilities) {
         if (jobs == null || jobs.size() == 0) {
             return false;
         }
 
         final Network network = mConnManager.getActiveNetworkForUid(jobs.valueAt(0).getSourceUid());
-        final int netId = network != null ? network.netId : -1;
-        NetworkCapabilities capabilities = networkToCapabilities.get(netId);
+        NetworkCapabilities capabilities = networkToCapabilities.get(network);
         if (capabilities == null) {
             capabilities = mConnManager.getNetworkCapabilities(network);
-            networkToCapabilities.put(netId, capabilities);
+            networkToCapabilities.put(network, capabilities);
         }
         final boolean networkMatch = (filterNetwork == null
                 || Objects.equals(filterNetwork, network));
diff --git a/apex/jobscheduler/service/java/com/android/server/job/controllers/JobStatus.java b/apex/jobscheduler/service/java/com/android/server/job/controllers/JobStatus.java
index adb4314..c76346f 100644
--- a/apex/jobscheduler/service/java/com/android/server/job/controllers/JobStatus.java
+++ b/apex/jobscheduler/service/java/com/android/server/job/controllers/JobStatus.java
@@ -28,7 +28,7 @@
 import android.net.Uri;
 import android.os.RemoteException;
 import android.os.UserHandle;
-import android.text.format.TimeMigrationUtils;
+import android.text.format.DateFormat;
 import android.util.ArraySet;
 import android.util.Pair;
 import android.util.Slog;
@@ -1518,7 +1518,7 @@
             if (job.getClipData() != null) {
                 pw.print(prefix); pw.print("  Clip data: ");
                 StringBuilder b = new StringBuilder(128);
-                job.getClipData().toShortString(b);
+                b.append(job.getClipData());
                 pw.println(b);
             }
             if (uriPerms != null) {
@@ -1659,14 +1659,18 @@
         }
         if (mLastSuccessfulRunTime != 0) {
             pw.print(prefix); pw.print("Last successful run: ");
-            pw.println(TimeMigrationUtils.formatMillisWithFixedFormat(mLastSuccessfulRunTime));
+            pw.println(formatTime(mLastSuccessfulRunTime));
         }
         if (mLastFailedRunTime != 0) {
             pw.print(prefix); pw.print("Last failed run: ");
-            pw.println(TimeMigrationUtils.formatMillisWithFixedFormat(mLastFailedRunTime));
+            pw.println(formatTime(mLastFailedRunTime));
         }
     }
 
+    private static CharSequence formatTime(long time) {
+        return DateFormat.format("yyyy-MM-dd HH:mm:ss", time);
+    }
+
     public void dump(ProtoOutputStream proto, long fieldId, boolean full, long elapsedRealtimeMillis) {
         final long token = proto.start(fieldId);
 
diff --git a/services/usage/java/com/android/server/usage/AppIdleHistory.java b/apex/jobscheduler/service/java/com/android/server/usage/AppIdleHistory.java
similarity index 100%
rename from services/usage/java/com/android/server/usage/AppIdleHistory.java
rename to apex/jobscheduler/service/java/com/android/server/usage/AppIdleHistory.java
diff --git a/services/usage/java/com/android/server/usage/AppStandbyController.java b/apex/jobscheduler/service/java/com/android/server/usage/AppStandbyController.java
similarity index 93%
rename from services/usage/java/com/android/server/usage/AppStandbyController.java
rename to apex/jobscheduler/service/java/com/android/server/usage/AppStandbyController.java
index 75e8fb5..7c472a9 100644
--- a/services/usage/java/com/android/server/usage/AppStandbyController.java
+++ b/apex/jobscheduler/service/java/com/android/server/usage/AppStandbyController.java
@@ -120,9 +120,9 @@
  * Manages the standby state of an app, listening to various events.
  *
  * Unit test:
-   atest ${ANDROID_BUILD_TOP}/frameworks/base/services/tests/servicestests/src/com/android/server/usage/AppStandbyControllerTests.java
+   atest com.android.server.usage.AppStandbyControllerTests
  */
-public class AppStandbyController {
+public class AppStandbyController implements AppStandbyInternal {
 
     private static final String TAG = "AppStandbyController";
     static final boolean DEBUG = false;
@@ -247,7 +247,7 @@
     /** The length of time phone must be charging before considered stable enough to run jobs  */
     long mStableChargingThresholdMillis;
 
-    volatile boolean mAppIdleEnabled;
+    private volatile boolean mAppIdleEnabled;
     boolean mAppIdleTempParoled;
     boolean mCharging;
     boolean mChargingStable;
@@ -320,7 +320,7 @@
         }
     }
 
-    AppStandbyController(Context context, Looper looper) {
+    public AppStandbyController(Context context, Looper looper) {
         this(new Injector(context, looper));
     }
 
@@ -351,6 +351,7 @@
                 null, mHandler);
     }
 
+    @VisibleForTesting
     void setAppIdleEnabled(boolean enabled) {
         synchronized (mAppIdleLock) {
             if (mAppIdleEnabled != enabled) {
@@ -363,6 +364,12 @@
         }
     }
 
+    @Override
+    public boolean isAppIdleEnabled() {
+        return mAppIdleEnabled;
+    }
+
+    @Override
     public void onBootPhase(int phase) {
         mInjector.onBootPhase(phase);
         if (phase == PHASE_SYSTEM_SERVICES_READY) {
@@ -400,7 +407,7 @@
         }
     }
 
-    void reportContentProviderUsage(String authority, String providerPkgName, int userId) {
+    private void reportContentProviderUsage(String authority, String providerPkgName, int userId) {
         if (!mAppIdleEnabled) return;
 
         // Get sync adapters for the authority
@@ -432,7 +439,7 @@
         }
     }
 
-    void reportExemptedSyncScheduled(String packageName, int userId) {
+    private void reportExemptedSyncScheduled(String packageName, int userId) {
         if (!mAppIdleEnabled) return;
 
         final int bucketToPromote;
@@ -463,7 +470,7 @@
         }
     }
 
-    void reportUnexemptedSyncScheduled(String packageName, int userId) {
+    private void reportUnexemptedSyncScheduled(String packageName, int userId) {
         if (!mAppIdleEnabled) return;
 
         final long elapsedRealtime = mInjector.elapsedRealtime();
@@ -482,7 +489,7 @@
         }
     }
 
-    void reportExemptedSyncStart(String packageName, int userId) {
+    private void reportExemptedSyncStart(String packageName, int userId) {
         if (!mAppIdleEnabled) return;
 
         final long elapsedRealtime = mInjector.elapsedRealtime();
@@ -497,6 +504,7 @@
         }
     }
 
+    @VisibleForTesting
     void setChargingState(boolean charging) {
         synchronized (mAppIdleLock) {
             if (mCharging != charging) {
@@ -517,7 +525,7 @@
         }
     }
 
-    void updateChargingStableState() {
+    private void updateChargingStableState() {
         synchronized (mAppIdleLock) {
             if (mChargingStable != mCharging) {
                 if (DEBUG) Slog.d(TAG, "Setting mChargingStable to " + mCharging);
@@ -527,8 +535,7 @@
         }
     }
 
-    /** Paroled here means temporary pardon from being inactive */
-    void setAppIdleParoled(boolean paroled) {
+    private void setAppIdleParoled(boolean paroled) {
         synchronized (mAppIdleLock) {
             final long now = mInjector.currentTimeMillis();
             if (mAppIdleTempParoled != paroled) {
@@ -545,7 +552,8 @@
         }
     }
 
-    boolean isParoledOrCharging() {
+    @Override
+    public boolean isParoledOrCharging() {
         if (!mAppIdleEnabled) return true;
         synchronized (mAppIdleLock) {
             // Only consider stable charging when determining charge state.
@@ -583,15 +591,13 @@
         mHandler.sendEmptyMessage(MSG_PAROLE_STATE_CHANGED);
     }
 
-    void postCheckIdleStates(int userId) {
+    @Override
+    public void postCheckIdleStates(int userId) {
         mHandler.sendMessage(mHandler.obtainMessage(MSG_CHECK_IDLE_STATES, userId, 0));
     }
 
-    /**
-     * We send a different message to check idle states once, otherwise we would end up
-     * scheduling a series of repeating checkIdleStates each time we fired off one.
-     */
-    void postOneTimeCheckIdleStates() {
+    @Override
+    public void postOneTimeCheckIdleStates() {
         if (mInjector.getBootPhase() < PHASE_SYSTEM_SERVICES_READY) {
             // Not booted yet; wait for it!
             mPendingOneTimeCheckIdleStates = true;
@@ -601,10 +607,7 @@
         }
     }
 
-    /**
-     * Check all running users' or specified user's apps to see if they enter an idle state.
-     * @return Returns whether checking should continue periodically.
-     */
+    @VisibleForTesting
     boolean checkIdleStates(int checkUserId) {
         if (!mAppIdleEnabled) {
             return false;
@@ -776,19 +779,15 @@
      * @return the bucket for the app, based on time since last used
      */
     @GuardedBy("mAppIdleLock")
-    @StandbyBuckets int getBucketForLocked(String packageName, int userId,
+    @StandbyBuckets
+    private int getBucketForLocked(String packageName, int userId,
             long elapsedRealtime) {
         int bucketIndex = mAppIdleHistory.getThresholdIndex(packageName, userId,
                 elapsedRealtime, mAppStandbyScreenThresholds, mAppStandbyElapsedThresholds);
         return THRESHOLD_BUCKETS[bucketIndex];
     }
 
-    /**
-     * Check if it's been a while since last parole and let idle apps do some work.
-     * If network is not available, delay parole until it is available up until the end of the
-     * parole window. Force the parole to be set if end of the parole window is reached.
-     */
-    void checkParoleTimeout() {
+    private void checkParoleTimeout() {
         boolean setParoled = false;
         boolean waitForNetwork = false;
         NetworkInfo activeNetwork = mConnectivityManager.getActiveNetworkInfo();
@@ -845,7 +844,7 @@
         }
     }
 
-    void onDeviceIdleModeChanged() {
+    private void onDeviceIdleModeChanged() {
         final boolean deviceIdle = mPowerManager.isDeviceIdleMode();
         if (DEBUG) Slog.i(TAG, "DeviceIdleMode changed to " + deviceIdle);
         boolean paroled = false;
@@ -869,67 +868,70 @@
         setAppIdleParoled(paroled);
     }
 
-    void reportEvent(UsageEvents.Event event, long elapsedRealtime, int userId) {
+    @Override
+    public void reportEvent(UsageEvents.Event event, long elapsedRealtime, int userId) {
         if (!mAppIdleEnabled) return;
         synchronized (mAppIdleLock) {
+            final String pkg = event.getPackageName();
+            final int eventType = event.getEventType();
             // TODO: Ideally this should call isAppIdleFiltered() to avoid calling back
             // about apps that are on some kind of whitelist anyway.
             final boolean previouslyIdle = mAppIdleHistory.isIdle(
-                    event.mPackage, userId, elapsedRealtime);
+                    pkg, userId, elapsedRealtime);
             // Inform listeners if necessary
-            if ((event.mEventType == UsageEvents.Event.ACTIVITY_RESUMED
-                    || event.mEventType == UsageEvents.Event.ACTIVITY_PAUSED
-                    || event.mEventType == UsageEvents.Event.SYSTEM_INTERACTION
-                    || event.mEventType == UsageEvents.Event.USER_INTERACTION
-                    || event.mEventType == UsageEvents.Event.NOTIFICATION_SEEN
-                    || event.mEventType == UsageEvents.Event.SLICE_PINNED
-                    || event.mEventType == UsageEvents.Event.SLICE_PINNED_PRIV
-                    || event.mEventType == UsageEvents.Event.FOREGROUND_SERVICE_START)) {
+            if ((eventType == UsageEvents.Event.ACTIVITY_RESUMED
+                    || eventType == UsageEvents.Event.ACTIVITY_PAUSED
+                    || eventType == UsageEvents.Event.SYSTEM_INTERACTION
+                    || eventType == UsageEvents.Event.USER_INTERACTION
+                    || eventType == UsageEvents.Event.NOTIFICATION_SEEN
+                    || eventType == UsageEvents.Event.SLICE_PINNED
+                    || eventType == UsageEvents.Event.SLICE_PINNED_PRIV
+                    || eventType == UsageEvents.Event.FOREGROUND_SERVICE_START)) {
 
                 final AppUsageHistory appHistory = mAppIdleHistory.getAppUsageHistory(
-                        event.mPackage, userId, elapsedRealtime);
+                        pkg, userId, elapsedRealtime);
                 final int prevBucket = appHistory.currentBucket;
                 final int prevBucketReason = appHistory.bucketingReason;
                 final long nextCheckTime;
-                final int subReason = usageEventToSubReason(event.mEventType);
+                final int subReason = usageEventToSubReason(eventType);
                 final int reason = REASON_MAIN_USAGE | subReason;
-                if (event.mEventType == UsageEvents.Event.NOTIFICATION_SEEN
-                        || event.mEventType == UsageEvents.Event.SLICE_PINNED) {
+                if (eventType == UsageEvents.Event.NOTIFICATION_SEEN
+                        || eventType == UsageEvents.Event.SLICE_PINNED) {
                     // Mild usage elevates to WORKING_SET but doesn't change usage time.
-                    mAppIdleHistory.reportUsage(appHistory, event.mPackage,
+                    mAppIdleHistory.reportUsage(appHistory, pkg,
                             STANDBY_BUCKET_WORKING_SET, subReason,
                             0, elapsedRealtime + mNotificationSeenTimeoutMillis);
                     nextCheckTime = mNotificationSeenTimeoutMillis;
-                } else if (event.mEventType == UsageEvents.Event.SYSTEM_INTERACTION) {
-                    mAppIdleHistory.reportUsage(appHistory, event.mPackage,
+                } else if (eventType == UsageEvents.Event.SYSTEM_INTERACTION) {
+                    mAppIdleHistory.reportUsage(appHistory, pkg,
                             STANDBY_BUCKET_ACTIVE, subReason,
                             0, elapsedRealtime + mSystemInteractionTimeoutMillis);
                     nextCheckTime = mSystemInteractionTimeoutMillis;
-                } else if (event.mEventType == UsageEvents.Event.FOREGROUND_SERVICE_START) {
+                } else if (eventType == UsageEvents.Event.FOREGROUND_SERVICE_START) {
                     // Only elevate bucket if this is the first usage of the app
                     if (prevBucket != STANDBY_BUCKET_NEVER) return;
-                    mAppIdleHistory.reportUsage(appHistory, event.mPackage,
+                    mAppIdleHistory.reportUsage(appHistory, pkg,
                             STANDBY_BUCKET_ACTIVE, subReason,
                             0, elapsedRealtime + mInitialForegroundServiceStartTimeoutMillis);
                     nextCheckTime = mInitialForegroundServiceStartTimeoutMillis;
                 } else {
-                    mAppIdleHistory.reportUsage(appHistory, event.mPackage,
+                    mAppIdleHistory.reportUsage(appHistory, pkg,
                             STANDBY_BUCKET_ACTIVE, subReason,
                             elapsedRealtime, elapsedRealtime + mStrongUsageTimeoutMillis);
                     nextCheckTime = mStrongUsageTimeoutMillis;
                 }
                 mHandler.sendMessageDelayed(mHandler.obtainMessage
-                        (MSG_CHECK_PACKAGE_IDLE_STATE, userId, -1, event.mPackage),
+                        (MSG_CHECK_PACKAGE_IDLE_STATE, userId, -1, pkg),
                         nextCheckTime);
                 final boolean userStartedInteracting =
                         appHistory.currentBucket == STANDBY_BUCKET_ACTIVE &&
                         prevBucket != appHistory.currentBucket &&
                         (prevBucketReason & REASON_MAIN_MASK) != REASON_MAIN_USAGE;
-                maybeInformListeners(event.mPackage, userId, elapsedRealtime,
+                maybeInformListeners(pkg, userId, elapsedRealtime,
                         appHistory.currentBucket, reason, userStartedInteracting);
 
                 if (previouslyIdle) {
-                    notifyBatteryStats(event.mPackage, userId, false);
+                    notifyBatteryStats(pkg, userId, false);
                 }
             }
         }
@@ -950,14 +952,7 @@
         }
     }
 
-    /**
-     * Forces the app's beginIdleTime and lastUsedTime to reflect idle or active. If idle,
-     * then it rolls back the beginIdleTime and lastUsedTime to a point in time that's behind
-     * the threshold for idle.
-     *
-     * This method is always called from the handler thread, so not much synchronization is
-     * required.
-     */
+    @VisibleForTesting
     void forceIdleState(String packageName, int userId, boolean idle) {
         if (!mAppIdleEnabled) return;
 
@@ -983,12 +978,14 @@
         }
     }
 
+    @Override
     public void setLastJobRunTime(String packageName, int userId, long elapsedRealtime) {
         synchronized (mAppIdleLock) {
             mAppIdleHistory.setLastJobRunTime(packageName, userId, elapsedRealtime);
         }
     }
 
+    @Override
     public long getTimeSinceLastJobRun(String packageName, int userId) {
         final long elapsedRealtime = mInjector.elapsedRealtime();
         synchronized (mAppIdleLock) {
@@ -996,6 +993,7 @@
         }
     }
 
+    @Override
     public void onUserRemoved(int userId) {
         synchronized (mAppIdleLock) {
             mAppIdleHistory.onUserRemoved(userId);
@@ -1011,7 +1009,8 @@
         }
     }
 
-    void addListener(AppIdleStateChangeListener listener) {
+    @Override
+    public void addListener(AppIdleStateChangeListener listener) {
         synchronized (mPackageAccessListeners) {
             if (!mPackageAccessListeners.contains(listener)) {
                 mPackageAccessListeners.add(listener);
@@ -1019,13 +1018,15 @@
         }
     }
 
-    void removeListener(AppIdleStateChangeListener listener) {
+    @Override
+    public void removeListener(AppIdleStateChangeListener listener) {
         synchronized (mPackageAccessListeners) {
             mPackageAccessListeners.remove(listener);
         }
     }
 
-    int getAppId(String packageName) {
+    @Override
+    public int getAppId(String packageName) {
         try {
             ApplicationInfo ai = mPackageManager.getApplicationInfo(packageName,
                     PackageManager.MATCH_ANY_USER
@@ -1036,7 +1037,8 @@
         }
     }
 
-    boolean isAppIdleFilteredOrParoled(String packageName, int userId, long elapsedRealtime,
+    @Override
+    public boolean isAppIdleFilteredOrParoled(String packageName, int userId, long elapsedRealtime,
             boolean shouldObfuscateInstantApps) {
         if (isParoledOrCharging()) {
             return false;
@@ -1048,8 +1050,7 @@
         return isAppIdleFiltered(packageName, getAppId(packageName), userId, elapsedRealtime);
     }
 
-    /** Returns true if this app should be whitelisted for some reason, to never go into standby */
-    boolean isAppSpecial(String packageName, int appId, int userId) {
+    private boolean isAppSpecial(String packageName, int appId, int userId) {
         if (packageName == null) return false;
         // If not enabled at all, of course nobody is ever idle.
         if (!mAppIdleEnabled) {
@@ -1102,13 +1103,8 @@
         return false;
     }
 
-    /**
-     * 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,
+    @Override
+    public boolean isAppIdleFiltered(String packageName, int appId, int userId,
             long elapsedRealtime) {
         if (isAppSpecial(packageName, appId, userId)) {
             return false;
@@ -1117,7 +1113,8 @@
         }
     }
 
-    int[] getIdleUidsForUser(int userId) {
+    @Override
+    public int[] getIdleUidsForUser(int userId) {
         if (!mAppIdleEnabled) {
             return new int[0];
         }
@@ -1181,13 +1178,15 @@
         return res;
     }
 
-    void setAppIdleAsync(String packageName, boolean idle, int userId) {
+    @Override
+    public void setAppIdleAsync(String packageName, boolean idle, int userId) {
         if (packageName == null || !mAppIdleEnabled) return;
 
         mHandler.obtainMessage(MSG_FORCE_IDLE_STATE, userId, idle ? 1 : 0, packageName)
                 .sendToTarget();
     }
 
+    @Override
     @StandbyBuckets public int getAppStandbyBucket(String packageName, int userId,
             long elapsedRealtime, boolean shouldObfuscateInstantApps) {
         if (!mAppIdleEnabled || (shouldObfuscateInstantApps
@@ -1200,18 +1199,21 @@
         }
     }
 
+    @Override
     public List<AppStandbyInfo> getAppStandbyBuckets(int userId) {
         synchronized (mAppIdleLock) {
             return mAppIdleHistory.getAppStandbyBuckets(userId, mAppIdleEnabled);
         }
     }
 
+    @VisibleForTesting
     void setAppStandbyBucket(String packageName, int userId, @StandbyBuckets int newBucket,
             int reason, long elapsedRealtime) {
         setAppStandbyBucket(packageName, userId, newBucket, reason, elapsedRealtime, false);
     }
 
-    void setAppStandbyBucket(String packageName, int userId, @StandbyBuckets int newBucket,
+    @Override
+    public void setAppStandbyBucket(String packageName, int userId, @StandbyBuckets int newBucket,
             int reason, long elapsedRealtime, boolean resetTimeout) {
         synchronized (mAppIdleLock) {
             // If the package is not installed, don't allow the bucket to be set.
@@ -1279,6 +1281,7 @@
         }
     }
 
+    @Override
     public void addActiveDeviceAdmin(String adminPkg, int userId) {
         synchronized (mActiveAdminApps) {
             Set<String> adminPkgs = mActiveAdminApps.get(userId);
@@ -1290,6 +1293,7 @@
         }
     }
 
+    @Override
     public void setActiveAdminApps(Set<String> adminPkgs, int userId) {
         synchronized (mActiveAdminApps) {
             if (adminPkgs == null) {
@@ -1300,6 +1304,7 @@
         }
     }
 
+    @Override
     public void onAdminDataAvailable() {
         mAdminDataAvailableLatch.countDown();
     }
@@ -1314,6 +1319,7 @@
         }
     }
 
+    @VisibleForTesting
     Set<String> getActiveAdminAppsForTest(int userId) {
         synchronized (mActiveAdminApps) {
             return mActiveAdminApps.get(userId);
@@ -1342,7 +1348,8 @@
         }
     }
 
-    void clearCarrierPrivilegedApps() {
+    @Override
+    public void clearCarrierPrivilegedApps() {
         if (DEBUG) {
             Slog.i(TAG, "Clearing carrier privileged apps list");
         }
@@ -1368,7 +1375,7 @@
         return packageName != null && packageName.equals(activeScorer);
     }
 
-    void informListeners(String packageName, int userId, int bucket, int reason,
+    private void informListeners(String packageName, int userId, int bucket, int reason,
             boolean userInteraction) {
         final boolean idle = bucket >= STANDBY_BUCKET_RARE;
         synchronized (mPackageAccessListeners) {
@@ -1381,7 +1388,7 @@
         }
     }
 
-    void informParoleStateChanged() {
+    private void informParoleStateChanged() {
         final boolean paroled = isParoledOrCharging();
         synchronized (mPackageAccessListeners) {
             for (AppIdleStateChangeListener listener : mPackageAccessListeners) {
@@ -1390,13 +1397,15 @@
         }
     }
 
-    void flushToDisk(int userId) {
+    @Override
+    public void flushToDisk(int userId) {
         synchronized (mAppIdleLock) {
             mAppIdleHistory.writeAppIdleTimes(userId);
         }
     }
 
-    void flushDurationsToDisk() {
+    @Override
+    public void flushDurationsToDisk() {
         // Persist elapsed and screen on time. If this fails for whatever reason, the apps will be
         // considered not-idle, which is the safest outcome in such an event.
         synchronized (mAppIdleLock) {
@@ -1404,10 +1413,11 @@
         }
     }
 
-    boolean isDisplayOn() {
+    private boolean isDisplayOn() {
         return mInjector.isDefaultDisplayOn();
     }
 
+    @VisibleForTesting
     void clearAppIdleForPackage(String packageName, int userId) {
         synchronized (mAppIdleLock) {
             mAppIdleHistory.clearUsage(packageName, userId);
@@ -1431,7 +1441,8 @@
         }
     }
 
-    void initializeDefaultsForSystemApps(int userId) {
+    @Override
+    public void initializeDefaultsForSystemApps(int userId) {
         if (!mSystemServicesReady) {
             // Do it later, since SettingsProvider wasn't queried yet for app_standby_enabled
             mPendingInitializeDefaults = true;
@@ -1461,7 +1472,8 @@
         }
     }
 
-    void postReportContentProviderUsage(String name, String packageName, int userId) {
+    @Override
+    public void postReportContentProviderUsage(String name, String packageName, int userId) {
         SomeArgs args = SomeArgs.obtain();
         args.arg1 = name;
         args.arg2 = packageName;
@@ -1470,23 +1482,27 @@
                 .sendToTarget();
     }
 
-    void postReportSyncScheduled(String packageName, int userId, boolean exempted) {
+    @Override
+    public void postReportSyncScheduled(String packageName, int userId, boolean exempted) {
         mHandler.obtainMessage(MSG_REPORT_SYNC_SCHEDULED, userId, exempted ? 1 : 0, packageName)
                 .sendToTarget();
     }
 
-    void postReportExemptedSyncStart(String packageName, int userId) {
+    @Override
+    public void postReportExemptedSyncStart(String packageName, int userId) {
         mHandler.obtainMessage(MSG_REPORT_EXEMPTED_SYNC_START, userId, 0, packageName)
                 .sendToTarget();
     }
 
-    void dumpUser(IndentingPrintWriter idpw, int userId, String pkg) {
+    @Override
+    public void dumpUser(IndentingPrintWriter idpw, int userId, String pkg) {
         synchronized (mAppIdleLock) {
             mAppIdleHistory.dump(idpw, userId, pkg);
         }
     }
 
-    void dumpState(String[] args, PrintWriter pw) {
+    @Override
+    public void dumpState(String[] args, PrintWriter pw) {
         synchronized (mAppIdleLock) {
             pw.println("Carrier privileged apps (have=" + mHaveCarrierPrivilegedApps
                     + "): " + mCarrierPrivilegedApps);
@@ -1835,16 +1851,6 @@
      * Observe settings changes for {@link Global#APP_IDLE_CONSTANTS}.
      */
     private class SettingsObserver extends ContentObserver {
-        /**
-         * This flag has been used to disable app idle on older builds with bug b/26355386.
-         */
-        @Deprecated
-        private static final String KEY_IDLE_DURATION_OLD = "idle_duration";
-        @Deprecated
-        private static final String KEY_IDLE_DURATION = "idle_duration2";
-        @Deprecated
-        private static final String KEY_WALLCLOCK_THRESHOLD = "wallclock_threshold";
-
         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";
@@ -1979,7 +1985,7 @@
                                         : DEFAULT_EXEMPTED_SYNC_START_TIMEOUT);
 
                 mUnexemptedSyncScheduledTimeoutMillis = mParser.getDurationMillis(
-                        KEY_EXEMPTED_SYNC_SCHEDULED_DOZE_HOLD_DURATION,
+                        KEY_UNEXEMPTED_SYNC_SCHEDULED_HOLD_DURATION,
                                 COMPRESS_TIME ? ONE_MINUTE
                                         : DEFAULT_UNEXEMPTED_SYNC_SCHEDULED_TIMEOUT); // TODO
 
diff --git a/apex/statsd/service/java/com/android/server/stats/StatsCompanionService.java b/apex/statsd/service/java/com/android/server/stats/StatsCompanionService.java
index 1d3ac6a..1a10753 100644
--- a/apex/statsd/service/java/com/android/server/stats/StatsCompanionService.java
+++ b/apex/statsd/service/java/com/android/server/stats/StatsCompanionService.java
@@ -2079,9 +2079,6 @@
             HistoricalOps histOps = ops.get(EXTERNAL_STATS_SYNC_TIMEOUT_MILLIS,
                     TimeUnit.MILLISECONDS);
 
-            StatsLogEventWrapper e = new StatsLogEventWrapper(StatsLog.APP_OPS, elapsedNanos,
-                    wallClockNanos);
-
             for (int uidIdx = 0; uidIdx < histOps.getUidCount(); uidIdx++) {
                 final HistoricalUidOps uidOps = histOps.getUidOpsAt(uidIdx);
                 final int uid = uidOps.getUid();
@@ -2089,6 +2086,9 @@
                     final HistoricalPackageOps packageOps = uidOps.getPackageOpsAt(pkgIdx);
                     for (int opIdx = 0; opIdx < packageOps.getOpCount(); opIdx++) {
                         final AppOpsManager.HistoricalOp op  = packageOps.getOpAt(opIdx);
+                        StatsLogEventWrapper e = new StatsLogEventWrapper(StatsLog.APP_OPS,
+                                elapsedNanos, wallClockNanos);
+
                         e.writeInt(uid);
                         e.writeString(packageOps.getPackageName());
                         e.writeInt(op.getOpCode());
diff --git a/api/current.txt b/api/current.txt
index 3ce043c..bd4a0c2 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -8,7 +8,6 @@
   public static final class Manifest.permission {
     ctor public Manifest.permission();
     field public static final String ACCEPT_HANDOVER = "android.permission.ACCEPT_HANDOVER";
-    field public static final String ACCESSIBILITY_SHORTCUT_TARGET = "android.permission.ACCESSIBILITY_SHORTCUT_TARGET";
     field public static final String ACCESS_BACKGROUND_LOCATION = "android.permission.ACCESS_BACKGROUND_LOCATION";
     field public static final String ACCESS_CHECKIN_PROPERTIES = "android.permission.ACCESS_CHECKIN_PROPERTIES";
     field public static final String ACCESS_COARSE_LOCATION = "android.permission.ACCESS_COARSE_LOCATION";
@@ -2834,6 +2833,7 @@
     method public final android.accessibilityservice.AccessibilityServiceInfo getServiceInfo();
     method @NonNull public final android.accessibilityservice.AccessibilityService.SoftKeyboardController getSoftKeyboardController();
     method public java.util.List<android.view.accessibility.AccessibilityWindowInfo> getWindows();
+    method @NonNull public final android.util.SparseArray<java.util.List<android.view.accessibility.AccessibilityWindowInfo>> getWindowsOnAllDisplays();
     method public abstract void onAccessibilityEvent(android.view.accessibility.AccessibilityEvent);
     method public final android.os.IBinder onBind(android.content.Intent);
     method @Deprecated protected boolean onGesture(int);
@@ -6363,6 +6363,7 @@
     method public android.view.WindowAnimationFrameStats getWindowAnimationFrameStats();
     method public android.view.WindowContentFrameStats getWindowContentFrameStats(int);
     method public java.util.List<android.view.accessibility.AccessibilityWindowInfo> getWindows();
+    method @NonNull public android.util.SparseArray<java.util.List<android.view.accessibility.AccessibilityWindowInfo>> getWindowsOnAllDisplays();
     method public void grantRuntimePermission(String, String);
     method public void grantRuntimePermissionAsUser(String, String, android.os.UserHandle);
     method public boolean injectInputEvent(android.view.InputEvent, boolean);
@@ -9678,6 +9679,7 @@
     field public static final String QUERY_ARG_SORT_COLLATION = "android:query-arg-sort-collation";
     field public static final String QUERY_ARG_SORT_COLUMNS = "android:query-arg-sort-columns";
     field public static final String QUERY_ARG_SORT_DIRECTION = "android:query-arg-sort-direction";
+    field public static final String QUERY_ARG_SORT_LOCALE = "android:query-arg-sort-locale";
     field public static final String QUERY_ARG_SQL_SELECTION = "android:query-arg-sql-selection";
     field public static final String QUERY_ARG_SQL_SELECTION_ARGS = "android:query-arg-sql-selection-args";
     field public static final String QUERY_ARG_SQL_SORT_ORDER = "android:query-arg-sql-sort-order";
@@ -9803,7 +9805,7 @@
     method public abstract java.io.File[] getExternalCacheDirs();
     method @Nullable public abstract java.io.File getExternalFilesDir(@Nullable String);
     method public abstract java.io.File[] getExternalFilesDirs(String);
-    method public abstract java.io.File[] getExternalMediaDirs();
+    method @Deprecated public abstract java.io.File[] getExternalMediaDirs();
     method public abstract java.io.File getFileStreamPath(String);
     method public abstract java.io.File getFilesDir();
     method public java.util.concurrent.Executor getMainExecutor();
@@ -10414,6 +10416,7 @@
     field public static final String ACTION_VOICE_COMMAND = "android.intent.action.VOICE_COMMAND";
     field @Deprecated public static final String ACTION_WALLPAPER_CHANGED = "android.intent.action.WALLPAPER_CHANGED";
     field public static final String ACTION_WEB_SEARCH = "android.intent.action.WEB_SEARCH";
+    field public static final String CATEGORY_ACCESSIBILITY_SHORTCUT_TARGET = "android.intent.category.ACCESSIBILITY_SHORTCUT_TARGET";
     field public static final String CATEGORY_ALTERNATIVE = "android.intent.category.ALTERNATIVE";
     field public static final String CATEGORY_APP_BROWSER = "android.intent.category.APP_BROWSER";
     field public static final String CATEGORY_APP_CALCULATOR = "android.intent.category.APP_CALCULATOR";
@@ -23965,6 +23968,7 @@
     ctor public ExifInterface(@NonNull String) throws java.io.IOException;
     ctor public ExifInterface(@NonNull java.io.FileDescriptor) throws java.io.IOException;
     ctor public ExifInterface(@NonNull java.io.InputStream) throws java.io.IOException;
+    method @NonNull public static android.media.ExifInterface fromStandalone(@NonNull java.io.InputStream) throws java.io.IOException;
     method public double getAltitude(double);
     method @Nullable public String getAttribute(@NonNull String);
     method @Nullable public byte[] getAttributeBytes(@NonNull String);
@@ -24352,6 +24356,7 @@
     field public static final int INFO_OUTPUT_FORMAT_CHANGED = -2; // 0xfffffffe
     field public static final int INFO_TRY_AGAIN_LATER = -1; // 0xffffffff
     field public static final String PARAMETER_KEY_HDR10_PLUS_INFO = "hdr10-plus-info";
+    field public static final String PARAMETER_KEY_LOW_LATENCY = "low-latency";
     field public static final String PARAMETER_KEY_OFFSET_TIME = "time-offset-us";
     field public static final String PARAMETER_KEY_REQUEST_SYNC_FRAME = "request-sync";
     field public static final String PARAMETER_KEY_SUSPEND = "drop-input-frames";
@@ -24525,6 +24530,7 @@
     field public static final String FEATURE_DynamicTimestamp = "dynamic-timestamp";
     field public static final String FEATURE_FrameParsing = "frame-parsing";
     field public static final String FEATURE_IntraRefresh = "intra-refresh";
+    field public static final String FEATURE_LowLatency = "low-latency";
     field public static final String FEATURE_MultipleFrames = "multiple-frames";
     field public static final String FEATURE_PartialFrame = "partial-frame";
     field public static final String FEATURE_SecurePlayback = "secure-playback";
@@ -25235,6 +25241,7 @@
     field public static final String KEY_LANGUAGE = "language";
     field public static final String KEY_LATENCY = "latency";
     field public static final String KEY_LEVEL = "level";
+    field public static final String KEY_LOW_LATENCY = "low-latency";
     field public static final String KEY_MAX_B_FRAMES = "max-bframes";
     field public static final String KEY_MAX_FPS_TO_ENCODER = "max-fps-to-encoder";
     field public static final String KEY_MAX_HEIGHT = "max-height";
@@ -25383,6 +25390,7 @@
     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 @NonNull public java.util.List<android.graphics.Bitmap> getFramesAtIndex(int, int, @NonNull android.media.MediaMetadataRetriever.BitmapParams);
@@ -25392,6 +25400,7 @@
     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 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;
@@ -25406,6 +25415,9 @@
     field public static final int METADATA_KEY_BITRATE = 20; // 0x14
     field public static final int METADATA_KEY_CAPTURE_FRAMERATE = 25; // 0x19
     field public static final int METADATA_KEY_CD_TRACK_NUMBER = 0; // 0x0
+    field public static final int METADATA_KEY_COLOR_RANGE = 37; // 0x25
+    field public static final int METADATA_KEY_COLOR_STANDARD = 35; // 0x23
+    field public static final int METADATA_KEY_COLOR_TRANSFER = 36; // 0x24
     field public static final int METADATA_KEY_COMPILATION = 15; // 0xf
     field public static final int METADATA_KEY_COMPOSER = 4; // 0x4
     field public static final int METADATA_KEY_DATE = 5; // 0x5
@@ -28805,6 +28817,7 @@
     method @Nullable public String getPrivateDnsServerName();
     method @NonNull public java.util.List<android.net.RouteInfo> getRoutes();
     method public boolean isPrivateDnsActive();
+    method public boolean isWakeOnLanSupported();
     method public void setDnsServers(@NonNull java.util.Collection<java.net.InetAddress>);
     method public void setDomains(@Nullable String);
     method public void setHttpProxy(@Nullable android.net.ProxyInfo);
@@ -38742,6 +38755,9 @@
     field public static final String ARTIST = "artist";
     field public static final String BOOKMARK = "bookmark";
     field public static final String CATEGORY = "category";
+    field public static final String COLOR_RANGE = "color_range";
+    field public static final String COLOR_STANDARD = "color_standard";
+    field public static final String COLOR_TRANSFER = "color_transfer";
     field public static final String DESCRIPTION = "description";
     field public static final String IS_PRIVATE = "isprivate";
     field public static final String LANGUAGE = "language";
@@ -40800,6 +40816,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";
   }
 
   public interface KeyChainAliasCallback {
@@ -45079,6 +45096,7 @@
     method @Nullable public android.telephony.TelephonyManager createForPhoneAccountHandle(android.telecom.PhoneAccountHandle);
     method public android.telephony.TelephonyManager createForSubscriptionId(int);
     method @RequiresPermission(android.Manifest.permission.READ_PHONE_STATE) public boolean doesSwitchMultiSimConfigTriggerReboot();
+    method public int getActiveModemCount();
     method @RequiresPermission(android.Manifest.permission.ACCESS_FINE_LOCATION) public java.util.List<android.telephony.CellInfo> getAllCellInfo();
     method public int getCallState();
     method public int getCardIdForDefaultEuicc();
@@ -45105,13 +45123,13 @@
     method @RequiresPermission("android.permission.READ_PRIVILEGED_PHONE_STATE") public String getMeid(int);
     method public String getMmsUAProfUrl();
     method public String getMmsUserAgent();
-    method @RequiresPermission(android.Manifest.permission.READ_PHONE_STATE) public String getNai();
+    method @RequiresPermission("android.permission.READ_PRIVILEGED_PHONE_STATE") public String getNai();
     method public String getNetworkCountryIso();
     method public String getNetworkOperator();
     method public String getNetworkOperatorName();
     method public String getNetworkSpecifier();
     method @Deprecated @RequiresPermission(android.Manifest.permission.READ_PHONE_STATE) public int getNetworkType();
-    method public int getPhoneCount();
+    method @Deprecated public int getPhoneCount();
     method public int getPhoneType();
     method @RequiresPermission(anyOf={"android.permission.READ_PRIVILEGED_PHONE_STATE", android.Manifest.permission.READ_PHONE_STATE}) public int getPreferredOpportunisticDataSubscription();
     method @RequiresPermission(allOf={android.Manifest.permission.READ_PHONE_STATE, android.Manifest.permission.ACCESS_COARSE_LOCATION}) public android.telephony.ServiceState getServiceState();
@@ -45127,6 +45145,7 @@
     method public int getSimState();
     method public int getSimState(int);
     method @RequiresPermission("android.permission.READ_PRIVILEGED_PHONE_STATE") public String getSubscriberId();
+    method public int getSupportedModemCount();
     method @Nullable public String getTypeAllocationCode();
     method @Nullable public String getTypeAllocationCode(int);
     method @RequiresPermission("android.permission.READ_PRIVILEGED_PHONE_STATE") @NonNull public java.util.List<android.telephony.UiccCardInfo> getUiccCardsInfo();
@@ -45164,6 +45183,7 @@
     method @RequiresPermission(android.Manifest.permission.CALL_PHONE) public void sendUssdRequest(String, android.telephony.TelephonyManager.UssdResponseCallback, android.os.Handler);
     method public void sendVisualVoicemailSms(String, int, String, android.app.PendingIntent);
     method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void setDataEnabled(boolean);
+    method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public int setForbiddenPlmns(@NonNull java.util.List<java.lang.String>);
     method public boolean setLine1NumberForDisplay(String, String);
     method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void setNetworkSelectionModeAutomatic();
     method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public boolean setNetworkSelectionModeManual(String, boolean);
@@ -45178,6 +45198,7 @@
     method public void updateAvailableNetworks(@NonNull java.util.List<android.telephony.AvailableNetworkInfo>, @Nullable java.util.concurrent.Executor, @Nullable java.util.function.Consumer<java.lang.Integer>);
     field public static final String ACTION_CARRIER_MESSAGING_CLIENT_SERVICE = "android.telephony.action.CARRIER_MESSAGING_CLIENT_SERVICE";
     field public static final String ACTION_CONFIGURE_VOICEMAIL = "android.telephony.action.CONFIGURE_VOICEMAIL";
+    field public static final String ACTION_MULTI_SIM_CONFIG_CHANGED = "android.telephony.action.MULTI_SIM_CONFIG_CHANGED";
     field public static final String ACTION_NETWORK_COUNTRY_CHANGED = "android.telephony.action.NETWORK_COUNTRY_CHANGED";
     field @RequiresPermission(android.Manifest.permission.READ_PHONE_STATE) public static final String ACTION_PHONE_STATE_CHANGED = "android.intent.action.PHONE_STATE";
     field public static final String ACTION_RESPOND_VIA_MESSAGE = "android.intent.action.RESPOND_VIA_MESSAGE";
@@ -45218,6 +45239,7 @@
     field public static final String EXTRA_LAUNCH_VOICEMAIL_SETTINGS_INTENT = "android.telephony.extra.LAUNCH_VOICEMAIL_SETTINGS_INTENT";
     field public static final String EXTRA_NETWORK_COUNTRY = "android.telephony.extra.NETWORK_COUNTRY";
     field public static final String EXTRA_NOTIFICATION_COUNT = "android.telephony.extra.NOTIFICATION_COUNT";
+    field public static final String EXTRA_NUM_OF_ACTIVE_SIM_SUPPORTED = "android.telephony.extra.NUM_OF_ACTIVE_SIM_SUPPORTED";
     field public static final String EXTRA_PHONE_ACCOUNT_HANDLE = "android.telephony.extra.PHONE_ACCOUNT_HANDLE";
     field public static final String EXTRA_SPECIFIC_CARRIER_ID = "android.telephony.extra.SPECIFIC_CARRIER_ID";
     field public static final String EXTRA_SPECIFIC_CARRIER_NAME = "android.telephony.extra.SPECIFIC_CARRIER_NAME";
@@ -45228,6 +45250,10 @@
     field public static final String EXTRA_SUBSCRIPTION_ID = "android.telephony.extra.SUBSCRIPTION_ID";
     field public static final String EXTRA_VOICEMAIL_NUMBER = "android.telephony.extra.VOICEMAIL_NUMBER";
     field public static final String METADATA_HIDE_VOICEMAIL_SETTINGS_MENU = "android.telephony.HIDE_VOICEMAIL_SETTINGS_MENU";
+    field public static final int MODEM_COUNT_DUAL_MODEM = 2; // 0x2
+    field public static final int MODEM_COUNT_NO_MODEM = 0; // 0x0
+    field public static final int MODEM_COUNT_SINGLE_MODEM = 1; // 0x1
+    field public static final int MODEM_COUNT_TRI_MODEM = 3; // 0x3
     field public static final int MULTISIM_ALLOWED = 0; // 0x0
     field public static final int MULTISIM_NOT_SUPPORTED_BY_CARRIER = 2; // 0x2
     field public static final int MULTISIM_NOT_SUPPORTED_BY_HARDWARE = 1; // 0x1
@@ -47129,7 +47155,9 @@
   public abstract class ReplacementSpan extends android.text.style.MetricAffectingSpan {
     ctor public ReplacementSpan();
     method public abstract void draw(@NonNull android.graphics.Canvas, CharSequence, @IntRange(from=0) int, @IntRange(from=0) int, float, int, int, int, @NonNull android.graphics.Paint);
+    method @Nullable public CharSequence getContentDescription();
     method public abstract int getSize(@NonNull android.graphics.Paint, CharSequence, @IntRange(from=0) int, @IntRange(from=0) int, @Nullable android.graphics.Paint.FontMetricsInt);
+    method public void setContentDescription(@Nullable CharSequence);
     method public void updateDrawState(android.text.TextPaint);
     method public void updateMeasureState(android.text.TextPaint);
   }
@@ -47903,6 +47931,7 @@
     ctor public ArraySet(int);
     ctor public ArraySet(android.util.ArraySet<E>);
     ctor public ArraySet(java.util.Collection<? extends E>);
+    ctor public ArraySet(@Nullable E[]);
     method public boolean add(E);
     method public void addAll(android.util.ArraySet<? extends E>);
     method public boolean addAll(java.util.Collection<? extends E>);
@@ -57410,7 +57439,7 @@
     method public boolean onPrivateIMECommand(String, android.os.Bundle);
     method public void onRestoreInstanceState(android.os.Parcelable);
     method public android.os.Parcelable onSaveInstanceState();
-    method protected void onSelectionChanged(int, int);
+    method @CallSuper protected void onSelectionChanged(int, int);
     method protected void onTextChanged(CharSequence, int, int, int);
     method public boolean onTextContextMenuItem(int);
     method public void removeTextChangedListener(android.text.TextWatcher);
diff --git a/api/system-current.txt b/api/system-current.txt
index c9f96e0..447ba30 100644
--- a/api/system-current.txt
+++ b/api/system-current.txt
@@ -24,6 +24,7 @@
     field public static final String BACKUP = "android.permission.BACKUP";
     field public static final String BIND_ATTENTION_SERVICE = "android.permission.BIND_ATTENTION_SERVICE";
     field public static final String BIND_AUGMENTED_AUTOFILL_SERVICE = "android.permission.BIND_AUGMENTED_AUTOFILL_SERVICE";
+    field public static final String BIND_CELL_BROADCAST_SERVICE = "android.permission.BIND_CELL_BROADCAST_SERVICE";
     field @Deprecated public static final String BIND_CONNECTION_SERVICE = "android.permission.BIND_CONNECTION_SERVICE";
     field public static final String BIND_CONTENT_CAPTURE_SERVICE = "android.permission.BIND_CONTENT_CAPTURE_SERVICE";
     field public static final String BIND_CONTENT_SUGGESTIONS_SERVICE = "android.permission.BIND_CONTENT_SUGGESTIONS_SERVICE";
@@ -225,6 +226,7 @@
     field public static final int isVrOnly = 16844152; // 0x1010578
     field public static final int requiredSystemPropertyName = 16844133; // 0x1010565
     field public static final int requiredSystemPropertyValue = 16844134; // 0x1010566
+    field public static final int resourcesMap = 16844297; // 0x1010609
     field public static final int supportsAmbientMode = 16844173; // 0x101058d
     field public static final int userRestriction = 16844164; // 0x1010584
   }
@@ -1357,8 +1359,9 @@
 
   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 public abstract android.content.Context createCredentialProtectedStorageContext();
-    method public android.content.Context createPackageContextAsUser(String, int, android.os.UserHandle) throws android.content.pm.PackageManager.NameNotFoundException;
+    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();
     method public abstract boolean isCredentialProtectedStorage();
     method public abstract void sendBroadcast(android.content.Intent, @Nullable String, @Nullable android.os.Bundle);
@@ -5519,7 +5522,7 @@
   public class UpdateEngine {
     ctor public UpdateEngine();
     method public void applyPayload(String, long, long, String[]);
-    method public void applyPayload(@NonNull java.io.FileDescriptor, long, long, @NonNull String[]);
+    method public void applyPayload(@NonNull android.os.ParcelFileDescriptor, long, long, @NonNull String[]);
     method public boolean bind(android.os.UpdateEngineCallback, android.os.Handler);
     method public boolean bind(android.os.UpdateEngineCallback);
     method public void cancel();
@@ -5874,6 +5877,7 @@
     method @RequiresPermission(android.Manifest.permission.READ_DEVICE_CONFIG) public static float getFloat(@NonNull String, @NonNull String, float);
     method @RequiresPermission(android.Manifest.permission.READ_DEVICE_CONFIG) public static int getInt(@NonNull String, @NonNull String, int);
     method @RequiresPermission(android.Manifest.permission.READ_DEVICE_CONFIG) public static long getLong(@NonNull String, @NonNull String, long);
+    method @NonNull @RequiresPermission(android.Manifest.permission.READ_DEVICE_CONFIG) public static android.provider.DeviceConfig.Properties getProperties(@NonNull String, @NonNull java.lang.String...);
     method @RequiresPermission(android.Manifest.permission.READ_DEVICE_CONFIG) public static String getProperty(@NonNull String, @NonNull String);
     method @RequiresPermission(android.Manifest.permission.READ_DEVICE_CONFIG) public static String getString(@NonNull String, @NonNull String, @Nullable String);
     method public static void removeOnPropertiesChangedListener(@NonNull android.provider.DeviceConfig.OnPropertiesChangedListener);
@@ -6361,6 +6365,7 @@
     method public android.os.IBinder onBind(android.content.Intent);
     method @Nullable public float[][] onCalculateScores(@NonNull java.util.List<android.view.autofill.AutofillValue>, @NonNull java.util.List<java.lang.String>, @NonNull java.util.List<java.lang.String>, @Nullable String, @Nullable android.os.Bundle, @Nullable java.util.Map, @Nullable java.util.Map);
     method @Deprecated @Nullable public float[][] onGetScores(@Nullable String, @Nullable android.os.Bundle, @NonNull java.util.List<android.view.autofill.AutofillValue>, @NonNull java.util.List<java.lang.String>);
+    field public static final String REQUIRED_ALGORITHM_CREDIT_CARD = "CREDIT_CARD";
     field public static final String REQUIRED_ALGORITHM_EDIT_DISTANCE = "EDIT_DISTANCE";
     field public static final String REQUIRED_ALGORITHM_EXACT_MATCH = "EXACT_MATCH";
     field public static final String SERVICE_INTERFACE = "android.service.autofill.AutofillFieldClassificationService";
@@ -6555,7 +6560,8 @@
     method public abstract int onDeleteSubscription(int, String);
     method public android.service.euicc.DownloadSubscriptionResult onDownloadSubscription(int, @NonNull android.telephony.euicc.DownloadableSubscription, boolean, boolean, @Nullable android.os.Bundle);
     method @Deprecated public int onDownloadSubscription(int, @NonNull android.telephony.euicc.DownloadableSubscription, boolean, boolean);
-    method public abstract int onEraseSubscriptions(int);
+    method @Deprecated public abstract int onEraseSubscriptions(int);
+    method public int onEraseSubscriptionsWithOptions(int, @android.telephony.euicc.EuiccCardManager.ResetOption int);
     method public abstract android.service.euicc.GetDefaultDownloadableSubscriptionListResult onGetDefaultDownloadableSubscriptionList(int, boolean);
     method public abstract android.service.euicc.GetDownloadableSubscriptionMetadataResult onGetDownloadableSubscriptionMetadata(int, android.telephony.euicc.DownloadableSubscription, boolean);
     method public abstract String onGetEid(int);
@@ -7303,6 +7309,14 @@
     method @NonNull public android.telephony.CarrierRestrictionRules.Builder setMultiSimPolicy(int);
   }
 
+  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 onGsmCellBroadcastSms(int, byte[]);
+    field public static final String CELL_BROADCAST_SERVICE_INTERFACE = "android.telephony.CellBroadcastService";
+  }
+
   public final class DataFailCause {
     field public static final int ACCESS_ATTEMPT_ALREADY_IN_PROGRESS = 2219; // 0x8ab
     field public static final int ACCESS_BLOCK = 2087; // 0x827
@@ -7875,8 +7889,8 @@
     field public static final int LISTEN_CALL_ATTRIBUTES_CHANGED = 67108864; // 0x4000000
     field @RequiresPermission("android.permission.READ_PRECISE_PHONE_STATE") public static final int LISTEN_CALL_DISCONNECT_CAUSES = 33554432; // 0x2000000
     field @RequiresPermission("android.permission.READ_PRECISE_PHONE_STATE") public static final int LISTEN_IMS_CALL_DISCONNECT_CAUSES = 134217728; // 0x8000000
-    field @RequiresPermission(android.Manifest.permission.READ_ACTIVE_EMERGENCY_SESSION) public static final int LISTEN_OUTGOING_CALL_EMERGENCY_NUMBER = 268435456; // 0x10000000
-    field @RequiresPermission(android.Manifest.permission.READ_ACTIVE_EMERGENCY_SESSION) public static final int LISTEN_OUTGOING_SMS_EMERGENCY_NUMBER = 536870912; // 0x20000000
+    field @RequiresPermission(android.Manifest.permission.READ_ACTIVE_EMERGENCY_SESSION) public static final int LISTEN_OUTGOING_EMERGENCY_CALL = 268435456; // 0x10000000
+    field @RequiresPermission(android.Manifest.permission.READ_ACTIVE_EMERGENCY_SESSION) public static final int LISTEN_OUTGOING_EMERGENCY_SMS = 536870912; // 0x20000000
     field @RequiresPermission("android.permission.READ_PRECISE_PHONE_STATE") public static final int LISTEN_PRECISE_CALL_STATE = 2048; // 0x800
     field @RequiresPermission("android.permission.READ_PRECISE_PHONE_STATE") public static final int LISTEN_PRECISE_DATA_CONNECTION_STATE = 4096; // 0x1000
     field public static final int LISTEN_RADIO_POWER_STATE_CHANGED = 8388608; // 0x800000
@@ -8104,7 +8118,7 @@
   }
 
   public final class SmsCbMessage implements android.os.Parcelable {
-    ctor public SmsCbMessage(int, int, int, @NonNull android.telephony.SmsCbLocation, int, @Nullable String, @Nullable String, int, @Nullable android.telephony.SmsCbEtwsInfo, @Nullable android.telephony.SmsCbCmasInfo);
+    ctor public SmsCbMessage(int, int, int, @NonNull android.telephony.SmsCbLocation, int, @Nullable String, @Nullable String, int, @Nullable android.telephony.SmsCbEtwsInfo, @Nullable android.telephony.SmsCbCmasInfo, int);
     method @NonNull public static android.telephony.SmsCbMessage createFromCursor(@NonNull android.database.Cursor);
     method public int describeContents();
     method @Nullable public android.telephony.SmsCbCmasInfo getCmasWarningInfo();
@@ -8119,6 +8133,7 @@
     method public long getReceivedTime();
     method public int getSerialNumber();
     method public int getServiceCategory();
+    method public int getSlotIndex();
     method public boolean isCmasMessage();
     method public boolean isEmergencyMessage();
     method public boolean isEtwsMessage();
@@ -8245,7 +8260,7 @@
     method @Nullable @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public String getIsimIst();
     method @NonNull @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public java.util.Map<java.lang.Integer,java.lang.Integer> getLogicalToPhysicalSlotMapping();
     method public static long getMaxNumberVerificationTimeoutMillis();
-    method @NonNull public String getNetworkCountryIso(int);
+    method @NonNull @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public String getNetworkCountryIso(int);
     method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public long getPreferredNetworkTypeBitmask();
     method @RequiresPermission(anyOf={android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE, android.Manifest.permission.READ_PHONE_STATE}) public int getRadioPowerState();
     method public int getSimApplicationState();
@@ -8266,6 +8281,7 @@
     method @Nullable @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public String iccTransmitApduLogicalChannelBySlot(int, int, int, int, int, int, int, @Nullable String);
     method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public boolean isApplicationOnUicc(int);
     method public boolean isDataConnectivityPossible();
+    method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public boolean isDataEnabledForApn(int);
     method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public boolean isEmergencyAssistanceEnabled();
     method @Deprecated @RequiresPermission(anyOf={android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE, android.Manifest.permission.READ_PHONE_STATE}) public boolean isIdle();
     method @Deprecated @RequiresPermission(anyOf={android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE, android.Manifest.permission.READ_PHONE_STATE}) public boolean isOffhook();
@@ -8608,7 +8624,8 @@
 
   public class EuiccManager {
     method @RequiresPermission(android.Manifest.permission.WRITE_EMBEDDED_SUBSCRIPTIONS) public void continueOperation(android.content.Intent, android.os.Bundle);
-    method @RequiresPermission(android.Manifest.permission.WRITE_EMBEDDED_SUBSCRIPTIONS) public void eraseSubscriptions(android.app.PendingIntent);
+    method @Deprecated @RequiresPermission(android.Manifest.permission.WRITE_EMBEDDED_SUBSCRIPTIONS) public void eraseSubscriptions(@NonNull android.app.PendingIntent);
+    method @RequiresPermission(android.Manifest.permission.WRITE_EMBEDDED_SUBSCRIPTIONS) public void eraseSubscriptionsWithOptions(@android.telephony.euicc.EuiccCardManager.ResetOption int, @NonNull android.app.PendingIntent);
     method @RequiresPermission(android.Manifest.permission.WRITE_EMBEDDED_SUBSCRIPTIONS) public void getDefaultDownloadableSubscriptionList(android.app.PendingIntent);
     method @RequiresPermission(android.Manifest.permission.WRITE_EMBEDDED_SUBSCRIPTIONS) public void getDownloadableSubscriptionMetadata(android.telephony.euicc.DownloadableSubscription, android.app.PendingIntent);
     method @RequiresPermission(android.Manifest.permission.WRITE_EMBEDDED_SUBSCRIPTIONS) public int getOtaStatus();
diff --git a/api/test-current.txt b/api/test-current.txt
index 0cf2f1b..fa28daf 100644
--- a/api/test-current.txt
+++ b/api/test-current.txt
@@ -5,6 +5,7 @@
     field public static final String ACCESS_NOTIFICATIONS = "android.permission.ACCESS_NOTIFICATIONS";
     field public static final String ACTIVITY_EMBEDDING = "android.permission.ACTIVITY_EMBEDDING";
     field public static final String APPROVE_INCIDENT_REPORTS = "android.permission.APPROVE_INCIDENT_REPORTS";
+    field public static final String BIND_CELL_BROADCAST_SERVICE = "android.permission.BIND_CELL_BROADCAST_SERVICE";
     field public static final String BRIGHTNESS_SLIDER_USAGE = "android.permission.BRIGHTNESS_SLIDER_USAGE";
     field public static final String CHANGE_APP_IDLE_STATE = "android.permission.CHANGE_APP_IDLE_STATE";
     field public static final String CLEAR_APP_USER_DATA = "android.permission.CLEAR_APP_USER_DATA";
@@ -130,7 +131,7 @@
     method public void startActivity(@NonNull android.content.Intent);
     method public void startActivity(@NonNull android.content.Intent, android.os.UserHandle);
     method public void startActivity(@NonNull android.app.PendingIntent);
-    method public void startActivity(@NonNull android.app.PendingIntent, @NonNull android.app.ActivityOptions);
+    method public void startActivity(@NonNull android.app.PendingIntent, @Nullable android.content.Intent, @NonNull android.app.ActivityOptions);
   }
 
   public abstract static class ActivityView.StateCallback {
@@ -658,7 +659,8 @@
   }
 
   public abstract class Context {
-    method public android.content.Context createPackageContextAsUser(String, int, android.os.UserHandle) throws android.content.pm.PackageManager.NameNotFoundException;
+    method @NonNull public android.content.Context createContextAsUser(@NonNull android.os.UserHandle);
+    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();
     method public android.os.UserHandle getUser();
@@ -1739,6 +1741,7 @@
   }
 
   public class DeviceIdleManager {
+    method @RequiresPermission("android.permission.DEVICE_POWER") public int addPowerSaveWhitelistApps(@NonNull java.util.List<java.lang.String>);
     method @NonNull public String[] getSystemPowerWhitelist();
     method @NonNull public String[] getSystemPowerWhitelistExceptIdle();
   }
@@ -2033,10 +2036,18 @@
   public final class UserHandle implements android.os.Parcelable {
     method public static int getAppId(int);
     method public int getIdentifier();
+    method public static int getUid(int, int);
+    method public static int getUserId(int);
     method public static boolean isApp(int);
+    method public static int myUserId();
+    method public static android.os.UserHandle of(int);
     field @NonNull public static final android.os.UserHandle ALL;
     field @NonNull public static final android.os.UserHandle CURRENT;
+    field public static final int MIN_SECONDARY_USER_ID = 10; // 0xa
     field @NonNull public static final android.os.UserHandle SYSTEM;
+    field public static final int USER_ALL = -1; // 0xffffffff
+    field public static final int USER_NULL = -10000; // 0xffffd8f0
+    field public static final int USER_SYSTEM = 0; // 0x0
   }
 
   public class UserManager {
@@ -2404,7 +2415,6 @@
     field public static final String LOCATION_ACCESS_CHECK_DELAY_MILLIS = "location_access_check_delay_millis";
     field public static final String LOCATION_ACCESS_CHECK_INTERVAL_MILLIS = "location_access_check_interval_millis";
     field public static final String NOTIFICATION_BADGING = "notification_badging";
-    field @Deprecated public static final String NOTIFICATION_BUBBLES = "notification_bubbles";
     field @RequiresPermission(android.Manifest.permission.WRITE_SECURE_SETTINGS) public static final String SYNC_PARENT_SOUNDS = "sync_parent_sounds";
     field public static final String USER_SETUP_COMPLETE = "user_setup_complete";
     field public static final String VOICE_INTERACTION_SERVICE = "voice_interaction_service";
@@ -2481,6 +2491,7 @@
   public abstract class AutofillFieldClassificationService extends android.app.Service {
     ctor public AutofillFieldClassificationService();
     method public android.os.IBinder onBind(android.content.Intent);
+    field public static final String REQUIRED_ALGORITHM_CREDIT_CARD = "CREDIT_CARD";
     field public static final String REQUIRED_ALGORITHM_EDIT_DISTANCE = "EDIT_DISTANCE";
     field public static final String REQUIRED_ALGORITHM_EXACT_MATCH = "EXACT_MATCH";
     field public static final String SERVICE_INTERFACE = "android.service.autofill.AutofillFieldClassificationService";
@@ -2900,8 +2911,10 @@
   }
 
   public class PhoneStateListener {
-    field @RequiresPermission("android.permission.READ_ACTIVE_EMERGENCY_SESSION") public static final int LISTEN_OUTGOING_CALL_EMERGENCY_NUMBER = 268435456; // 0x10000000
-    field @RequiresPermission("android.permission.READ_ACTIVE_EMERGENCY_SESSION") public static final int LISTEN_OUTGOING_SMS_EMERGENCY_NUMBER = 536870912; // 0x20000000
+    method public void onOutgoingEmergencyCall(@NonNull android.telephony.emergency.EmergencyNumber);
+    method public void onOutgoingEmergencySms(@NonNull android.telephony.emergency.EmergencyNumber);
+    field @RequiresPermission("android.permission.READ_ACTIVE_EMERGENCY_SESSION") public static final int LISTEN_OUTGOING_EMERGENCY_CALL = 268435456; // 0x10000000
+    field @RequiresPermission("android.permission.READ_ACTIVE_EMERGENCY_SESSION") public static final int LISTEN_OUTGOING_EMERGENCY_SMS = 536870912; // 0x20000000
   }
 
   public class ServiceState implements android.os.Parcelable {
@@ -2928,7 +2941,7 @@
     method public int checkCarrierPrivilegesForPackage(String);
     method public int getCarrierIdListVersion();
     method @RequiresPermission(android.Manifest.permission.READ_PHONE_STATE) public String getLine1AlphaTag();
-    method @NonNull public String getNetworkCountryIso(int);
+    method @NonNull @RequiresPermission("android.permission.READ_PRIVILEGED_PHONE_STATE") public String getNetworkCountryIso(int);
     method public android.util.Pair<java.lang.Integer,java.lang.Integer> getRadioHalVersion();
     method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void refreshUiccProfile();
     method @Deprecated public void setCarrierTestOverride(String, String, String, String, String, String, String);
diff --git a/cmds/idmap2/Android.bp b/cmds/idmap2/Android.bp
index 4c77ba4..41a1706 100644
--- a/cmds/idmap2/Android.bp
+++ b/cmds/idmap2/Android.bp
@@ -43,9 +43,10 @@
         "libidmap2/Policies.cpp",
         "libidmap2/PrettyPrintVisitor.cpp",
         "libidmap2/RawPrintVisitor.cpp",
+        "libidmap2/ResourceMapping.cpp",
         "libidmap2/ResourceUtils.cpp",
         "libidmap2/Result.cpp",
-        "libidmap2/Xml.cpp",
+        "libidmap2/XmlParser.cpp",
         "libidmap2/ZipFile.cpp",
     ],
     export_include_dirs: ["include"],
@@ -97,9 +98,10 @@
         "tests/PoliciesTests.cpp",
         "tests/PrettyPrintVisitorTests.cpp",
         "tests/RawPrintVisitorTests.cpp",
+        "tests/ResourceMappingTests.cpp",
         "tests/ResourceUtilsTests.cpp",
         "tests/ResultTests.cpp",
-        "tests/XmlTests.cpp",
+        "tests/XmlParserTests.cpp",
         "tests/ZipFileTests.cpp",
     ],
     required: [
diff --git a/cmds/idmap2/idmap2/Create.cpp b/cmds/idmap2/idmap2/Create.cpp
index f482191..3ff6d35 100644
--- a/cmds/idmap2/idmap2/Create.cpp
+++ b/cmds/idmap2/idmap2/Create.cpp
@@ -99,8 +99,8 @@
     return Error("failed to load apk %s", overlay_apk_path.c_str());
   }
 
-  const auto idmap = Idmap::FromApkAssets(target_apk_path, *target_apk, overlay_apk_path,
-                                          *overlay_apk, fulfilled_policies, !ignore_overlayable);
+  const auto idmap =
+      Idmap::FromApkAssets(*target_apk, *overlay_apk, fulfilled_policies, !ignore_overlayable);
   if (!idmap) {
     return Error(idmap.GetError(), "failed to create idmap");
   }
diff --git a/cmds/idmap2/idmap2/Lookup.cpp b/cmds/idmap2/idmap2/Lookup.cpp
index b7ae9d0..c5cf980 100644
--- a/cmds/idmap2/idmap2/Lookup.cpp
+++ b/cmds/idmap2/idmap2/Lookup.cpp
@@ -33,9 +33,10 @@
 #include "androidfw/Util.h"
 #include "idmap2/CommandLineOptions.h"
 #include "idmap2/Idmap.h"
+#include "idmap2/ResourceUtils.h"
 #include "idmap2/Result.h"
 #include "idmap2/SysTrace.h"
-#include "idmap2/Xml.h"
+#include "idmap2/XmlParser.h"
 #include "idmap2/ZipFile.h"
 #include "utils/String16.h"
 #include "utils/String8.h"
@@ -57,8 +58,7 @@
 using android::idmap2::ResourceId;
 using android::idmap2::Result;
 using android::idmap2::Unit;
-using android::idmap2::Xml;
-using android::idmap2::ZipFile;
+using android::idmap2::utils::ExtractOverlayManifestInfo;
 using android::util::Utf16ToUtf8;
 
 namespace {
@@ -132,29 +132,6 @@
   return out;
 }
 
-Result<std::string> GetTargetPackageNameFromManifest(const std::string& apk_path) {
-  const auto zip = ZipFile::Open(apk_path);
-  if (!zip) {
-    return Error("failed to open %s as zip", apk_path.c_str());
-  }
-  const auto entry = zip->Uncompress("AndroidManifest.xml");
-  if (!entry) {
-    return Error("failed to uncompress AndroidManifest.xml in %s", apk_path.c_str());
-  }
-  const auto xml = Xml::Create(entry->buf, entry->size);
-  if (!xml) {
-    return Error("failed to create XML buffer");
-  }
-  const auto tag = xml->FindTag("overlay");
-  if (!tag) {
-    return Error("failed to find <overlay> tag");
-  }
-  const auto iter = tag->find("targetPackage");
-  if (iter == tag->end()) {
-    return Error("failed to find targetPackage attribute");
-  }
-  return iter->second;
-}
 }  // namespace
 
 Result<Unit> Lookup(const std::vector<std::string>& args) {
@@ -202,12 +179,12 @@
       }
       apk_assets.push_back(std::move(target_apk));
 
-      const Result<std::string> package_name =
-          GetTargetPackageNameFromManifest(idmap_header->GetOverlayPath().to_string());
-      if (!package_name) {
-        return Error("failed to parse android:targetPackage from overlay manifest");
+      auto manifest_info = ExtractOverlayManifestInfo(idmap_header->GetOverlayPath().to_string(),
+                                                      true /* assert_overlay */);
+      if (!manifest_info) {
+        return manifest_info.GetError();
       }
-      target_package_name = *package_name;
+      target_package_name = (*manifest_info).target_package;
     } else if (target_path != idmap_header->GetTargetPath()) {
       return Error("different target APKs (expected target APK %s but %s has target APK %s)",
                    target_path.c_str(), idmap_path.c_str(),
diff --git a/cmds/idmap2/idmap2/Scan.cpp b/cmds/idmap2/idmap2/Scan.cpp
index d0530f2..e643ab5 100644
--- a/cmds/idmap2/idmap2/Scan.cpp
+++ b/cmds/idmap2/idmap2/Scan.cpp
@@ -33,7 +33,7 @@
 #include "idmap2/ResourceUtils.h"
 #include "idmap2/Result.h"
 #include "idmap2/SysTrace.h"
-#include "idmap2/Xml.h"
+#include "idmap2/XmlParser.h"
 #include "idmap2/ZipFile.h"
 
 using android::idmap2::CommandLineOptions;
diff --git a/cmds/idmap2/idmap2d/Idmap2Service.cpp b/cmds/idmap2/idmap2d/Idmap2Service.cpp
index 8ee79f6..4aabf83 100644
--- a/cmds/idmap2/idmap2d/Idmap2Service.cpp
+++ b/cmds/idmap2/idmap2d/Idmap2Service.cpp
@@ -137,8 +137,8 @@
     return error("failed to load apk " + overlay_apk_path);
   }
 
-  const auto idmap = Idmap::FromApkAssets(target_apk_path, *target_apk, overlay_apk_path,
-                                          *overlay_apk, policy_bitmask, enforce_overlayable);
+  const auto idmap =
+      Idmap::FromApkAssets(*target_apk, *overlay_apk, policy_bitmask, enforce_overlayable);
   if (!idmap) {
     return error(idmap.GetErrorMessage());
   }
diff --git a/cmds/idmap2/include/idmap2/Idmap.h b/cmds/idmap2/include/idmap2/Idmap.h
index ebbb5ff..f2cae58 100644
--- a/cmds/idmap2/include/idmap2/Idmap.h
+++ b/cmds/idmap2/include/idmap2/Idmap.h
@@ -56,20 +56,14 @@
 #include "androidfw/ResourceTypes.h"
 #include "androidfw/StringPiece.h"
 #include "idmap2/Policies.h"
+#include "idmap2/ResourceMapping.h"
 
 namespace android::idmap2 {
 
 class Idmap;
 class Visitor;
 
-// use typedefs to let the compiler warn us about implicit casts
-typedef uint32_t ResourceId;  // 0xpptteeee
-typedef uint8_t PackageId;    // pp in 0xpptteeee
-typedef uint8_t TypeId;       // tt in 0xpptteeee
-typedef uint16_t EntryId;     // eeee in 0xpptteeee
-
 static constexpr const ResourceId kPadding = 0xffffffffu;
-
 static constexpr const EntryId kNoEntry = 0xffffu;
 
 // magic number: all idmap files start with this
@@ -155,7 +149,7 @@
     PackageId target_package_id_;
     uint16_t type_count_;
 
-    friend Idmap;
+    friend IdmapData;
     DISALLOW_COPY_AND_ASSIGN(Header);
   };
 
@@ -194,12 +188,15 @@
     uint16_t entry_offset_;
     std::vector<EntryId> entries_;
 
-    friend Idmap;
+    friend IdmapData;
     DISALLOW_COPY_AND_ASSIGN(TypeEntry);
   };
 
   static std::unique_ptr<const IdmapData> FromBinaryStream(std::istream& stream);
 
+  static Result<std::unique_ptr<const IdmapData>> FromResourceMapping(
+      const ResourceMapping& resource_mapping);
+
   inline const std::unique_ptr<const Header>& GetHeader() const {
     return header_;
   }
@@ -232,9 +229,7 @@
   // file is used; change this in the next version of idmap to use a named
   // package instead; also update FromApkAssets to take additional parameters:
   // the target and overlay package names
-  static Result<std::unique_ptr<const Idmap>> FromApkAssets(const std::string& target_apk_path,
-                                                            const ApkAssets& target_apk_assets,
-                                                            const std::string& overlay_apk_path,
+  static Result<std::unique_ptr<const Idmap>> FromApkAssets(const ApkAssets& target_apk_assets,
                                                             const ApkAssets& overlay_apk_assets,
                                                             const PolicyBitmask& fulfilled_policies,
                                                             bool enforce_overlayable);
diff --git a/cmds/idmap2/include/idmap2/ResourceMapping.h b/cmds/idmap2/include/idmap2/ResourceMapping.h
new file mode 100644
index 0000000..c3e1ef0
--- /dev/null
+++ b/cmds/idmap2/include/idmap2/ResourceMapping.h
@@ -0,0 +1,132 @@
+/*
+ * 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 IDMAP2_INCLUDE_IDMAP2_RESOURCEMAPPING_H_
+#define IDMAP2_INCLUDE_IDMAP2_RESOURCEMAPPING_H_
+
+#include <map>
+#include <memory>
+#include <utility>
+
+#include "androidfw/ApkAssets.h"
+#include "idmap2/Policies.h"
+#include "idmap2/ResourceUtils.h"
+#include "idmap2/Result.h"
+#include "idmap2/XmlParser.h"
+
+using android::idmap2::utils::OverlayManifestInfo;
+
+namespace android::idmap2 {
+
+struct TargetValue {
+  typedef uint8_t DataType;
+  typedef uint32_t DataValue;
+  DataType data_type;
+  DataValue data_value;
+};
+
+using TargetResourceMap = std::map<ResourceId, TargetValue>;
+using OverlayResourceMap = std::map<ResourceId, ResourceId>;
+
+class ResourceMapping {
+ public:
+  // Creates a ResourceMapping using the target and overlay APKs. Setting enforce_overlayable to
+  // `false` disables all overlayable and policy enforcement: this is intended for backwards
+  // compatibility pre-Q and unit tests.
+  static Result<ResourceMapping> FromApkAssets(const ApkAssets& target_apk_assets,
+                                               const ApkAssets& overlay_apk_assets,
+                                               const OverlayManifestInfo& overlay_info,
+                                               const PolicyBitmask& fulfilled_policies,
+                                               bool enforce_overlayable);
+
+  // Retrieves the mapping of target resource id to overlay value.
+  inline TargetResourceMap GetTargetToOverlayMap() const {
+    return target_map_;
+  }
+
+  // Retrieves the mapping of overlay resource id to target resource id. This allows a reference to
+  // an overlay resource to appear as a reference to its corresponding target resource at runtime.
+  OverlayResourceMap GetOverlayToTargetMap() const;
+
+  // Retrieves the build-time package id of the target package.
+  inline uint32_t GetTargetPackageId() const {
+    return target_package_id_;
+  }
+
+  // Retrieves the build-time package id of the overlay package.
+  inline uint32_t GetOverlayPackageId() const {
+    return overlay_package_id_;
+  }
+
+  // Retrieves the offset that was added to the index of inline string overlay values so the indices
+  // do not collide with the indices of the overlay resource table string pool.
+  inline uint32_t GetStringPoolOffset() const {
+    return string_pool_offset_;
+  }
+
+  // Retrieves the raw string pool data from the xml referenced in android:resourcesMap.
+  inline const std::pair<const uint8_t*, uint32_t> GetStringPoolData() const {
+    return std::make_pair(string_pool_data_.get(), string_pool_data_length_);
+  }
+
+ private:
+  ResourceMapping() = default;
+
+  // Apps a mapping of target resource id to the type and value of the data that overlays the
+  // target resource. The data_type is the runtime format of the data value (see
+  // Res_value::dataType). If rewrite_overlay_reference is `true` then references to an overlay
+  // resource should appear as a reference to its corresponding target resource at runtime.
+  Result<Unit> AddMapping(ResourceId target_resource, TargetValue::DataType data_type,
+                          TargetValue::DataValue data_value, bool rewrite_overlay_reference);
+
+  // Removes the overlay value mapping for the target resource.
+  void RemoveMapping(ResourceId target_resource);
+
+  // Parses the mapping of target resources to overlay resources to generate a ResourceMapping.
+  static Result<ResourceMapping> CreateResourceMapping(const AssetManager2* target_am,
+                                                       const LoadedPackage* target_package,
+                                                       const LoadedPackage* overlay_package,
+                                                       size_t string_pool_offset,
+                                                       const XmlParser& overlay_parser);
+
+  // Generates a ResourceMapping that maps target resources to overlay resources by name. To overlay
+  // a target resource, a resource must exist in the overlay with the same type and entry name as
+  // the target resource.
+  static Result<ResourceMapping> CreateResourceMappingLegacy(const AssetManager2* target_am,
+                                                             const AssetManager2* overlay_am,
+                                                             const LoadedPackage* target_package,
+                                                             const LoadedPackage* overlay_package);
+
+  // Removes resources that do not pass policy or overlayable checks of the target package.
+  void FilterOverlayableResources(const AssetManager2* target_am,
+                                  const LoadedPackage* target_package,
+                                  const LoadedPackage* overlay_package,
+                                  const OverlayManifestInfo& overlay_info,
+                                  const PolicyBitmask& fulfilled_policies);
+
+  TargetResourceMap target_map_;
+  std::multimap<ResourceId, ResourceId> overlay_map_;
+
+  uint32_t target_package_id_ = 0;
+  uint32_t overlay_package_id_ = 0;
+  uint32_t string_pool_offset_ = 0;
+  uint32_t string_pool_data_length_ = 0;
+  std::unique_ptr<uint8_t[]> string_pool_data_ = nullptr;
+};
+
+}  // namespace android::idmap2
+
+#endif  // IDMAP2_INCLUDE_IDMAP2_RESOURCEMAPPING_H_
diff --git a/cmds/idmap2/include/idmap2/ResourceUtils.h b/cmds/idmap2/include/idmap2/ResourceUtils.h
index 9a0c2ab..abc2df1 100644
--- a/cmds/idmap2/include/idmap2/ResourceUtils.h
+++ b/cmds/idmap2/include/idmap2/ResourceUtils.h
@@ -21,17 +21,28 @@
 #include <string>
 
 #include "androidfw/AssetManager2.h"
-#include "idmap2/Idmap.h"
 #include "idmap2/Result.h"
 #include "idmap2/ZipFile.h"
 
-namespace android::idmap2::utils {
+namespace android::idmap2 {
+
+// use typedefs to let the compiler warn us about implicit casts
+typedef uint32_t ResourceId;  // 0xpptteeee
+typedef uint8_t PackageId;    // pp in 0xpptteeee
+typedef uint8_t TypeId;       // tt in 0xpptteeee
+typedef uint16_t EntryId;     // eeee in 0xpptteeee
+
+#define EXTRACT_TYPE(resid) ((0x00ff0000 & (resid)) >> 16)
+#define EXTRACT_ENTRY(resid) (0x0000ffff & (resid))
+
+namespace utils {
 
 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 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)
 };
@@ -41,6 +52,8 @@
 
 Result<std::string> ResToTypeEntryName(const AssetManager2& am, ResourceId resid);
 
-}  // namespace android::idmap2::utils
+}  // namespace utils
+
+}  // namespace android::idmap2
 
 #endif  // IDMAP2_INCLUDE_IDMAP2_RESOURCEUTILS_H_
diff --git a/cmds/idmap2/include/idmap2/Xml.h b/cmds/idmap2/include/idmap2/Xml.h
deleted file mode 100644
index dd89dee..0000000
--- a/cmds/idmap2/include/idmap2/Xml.h
+++ /dev/null
@@ -1,49 +0,0 @@
-/*
- * Copyright (C) 2018 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef IDMAP2_INCLUDE_IDMAP2_XML_H_
-#define IDMAP2_INCLUDE_IDMAP2_XML_H_
-
-#include <map>
-#include <memory>
-#include <string>
-
-#include "android-base/macros.h"
-#include "androidfw/ResourceTypes.h"
-#include "utils/String16.h"
-
-namespace android::idmap2 {
-
-class Xml {
- public:
-  static std::unique_ptr<const Xml> Create(const uint8_t* data, size_t size, bool copyData = false);
-
-  std::unique_ptr<std::map<std::string, std::string>> FindTag(const std::string& name) const;
-
-  ~Xml();
-
- private:
-  Xml() {
-  }
-
-  mutable ResXMLTree xml_;
-
-  DISALLOW_COPY_AND_ASSIGN(Xml);
-};
-
-}  // namespace android::idmap2
-
-#endif  // IDMAP2_INCLUDE_IDMAP2_XML_H_
diff --git a/cmds/idmap2/include/idmap2/XmlParser.h b/cmds/idmap2/include/idmap2/XmlParser.h
new file mode 100644
index 0000000..972a6d7
--- /dev/null
+++ b/cmds/idmap2/include/idmap2/XmlParser.h
@@ -0,0 +1,147 @@
+/*
+ * 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 IDMAP2_INCLUDE_IDMAP2_XMLPARSER_H_
+#define IDMAP2_INCLUDE_IDMAP2_XMLPARSER_H_
+
+#include <iostream>
+#include <map>
+#include <memory>
+#include <string>
+
+#include "Result.h"
+#include "android-base/macros.h"
+#include "androidfw/ResourceTypes.h"
+#include "utils/String16.h"
+
+namespace android::idmap2 {
+
+class XmlParser {
+ public:
+  using Event = ResXMLParser::event_code_t;
+  class iterator;
+
+  class Node {
+   public:
+    Event event() const;
+    std::string name() const;
+
+    Result<std::string> GetAttributeStringValue(const std::string& name) const;
+    Result<Res_value> GetAttributeValue(const std::string& name) const;
+
+    bool operator==(const Node& rhs) const;
+    bool operator!=(const Node& rhs) const;
+
+   private:
+    explicit Node(const ResXMLTree& tree);
+    Node(const ResXMLTree& tree, const ResXMLParser::ResXMLPosition& pos);
+
+    // Retrieves/Sets the position of the position of the xml parser in the xml tree.
+    ResXMLParser::ResXMLPosition get_position() const;
+    void set_position(const ResXMLParser::ResXMLPosition& pos);
+
+    // If `inner_child` is true, seek advances the parser to the first inner child of the current
+    // node. Otherwise, seek advances the parser to the following node. Returns false if there is
+    // no node to seek to.
+    bool Seek(bool inner_child);
+
+    ResXMLParser parser_;
+    friend iterator;
+  };
+
+  class iterator {
+   public:
+    iterator(const iterator& other) : iterator(other.tree_, other.iter_) {
+    }
+
+    inline iterator& operator=(const iterator& rhs) {
+      iter_.set_position(rhs.iter_.get_position());
+      return *this;
+    }
+
+    inline bool operator==(const iterator& rhs) const {
+      return iter_ == rhs.iter_;
+    }
+
+    inline bool operator!=(const iterator& rhs) const {
+      return !(*this == rhs);
+    }
+
+    inline iterator operator++() {
+      // Seek to the following xml node.
+      iter_.Seek(false /* inner_child */);
+      return *this;
+    }
+
+    iterator begin() const {
+      iterator child_it(*this);
+      // Seek to the first inner child of the current node.
+      child_it.iter_.Seek(true /* inner_child */);
+      return child_it;
+    }
+
+    iterator end() const {
+      iterator child_it = begin();
+      while (child_it.iter_.Seek(false /* inner_child */)) {
+        // Continue iterating until the end tag is found.
+      }
+
+      return child_it;
+    }
+
+    inline const Node operator*() {
+      return Node(tree_, iter_.get_position());
+    }
+
+    inline const Node* operator->() {
+      return &iter_;
+    }
+
+   private:
+    explicit iterator(const ResXMLTree& tree) : tree_(tree), iter_(Node(tree)) {
+    }
+    iterator(const ResXMLTree& tree, const Node& node)
+        : tree_(tree), iter_(Node(tree, node.get_position())) {
+    }
+
+    const ResXMLTree& tree_;
+    Node iter_;
+    friend XmlParser;
+  };
+
+  // Creates a new xml parser beginning at the first tag.
+  static Result<std::unique_ptr<const XmlParser>> Create(const void* data, size_t size,
+                                                         bool copy_data = false);
+  ~XmlParser();
+
+  inline iterator tree_iterator() const {
+    return iterator(tree_);
+  }
+
+  inline const ResStringPool& get_strings() const {
+    return tree_.getStrings();
+  }
+
+ private:
+  XmlParser() = default;
+  mutable ResXMLTree tree_;
+
+  DISALLOW_COPY_AND_ASSIGN(XmlParser);
+};
+
+}  // namespace android::idmap2
+
+#endif  // IDMAP2_INCLUDE_IDMAP2_XMLPARSER_H_
diff --git a/cmds/idmap2/libidmap2/Idmap.cpp b/cmds/idmap2/libidmap2/Idmap.cpp
index 4649675..389ade5 100644
--- a/cmds/idmap2/libidmap2/Idmap.cpp
+++ b/cmds/idmap2/libidmap2/Idmap.cpp
@@ -30,6 +30,7 @@
 #include "android-base/macros.h"
 #include "android-base/stringprintf.h"
 #include "androidfw/AssetManager2.h"
+#include "idmap2/ResourceMapping.h"
 #include "idmap2/ResourceUtils.h"
 #include "idmap2/Result.h"
 #include "idmap2/SysTrace.h"
@@ -41,10 +42,6 @@
 
 namespace {
 
-#define EXTRACT_TYPE(resid) ((0x00ff0000 & (resid)) >> 16)
-
-#define EXTRACT_ENTRY(resid) (0x0000ffff & (resid))
-
 class MatchingResources {
  public:
   void Add(ResourceId target_resid, ResourceId overlay_resid) {
@@ -97,28 +94,6 @@
   return true;
 }
 
-ResourceId NameToResid(const AssetManager2& am, const std::string& name) {
-  return am.GetResourceId(name);
-}
-
-// TODO(martenkongstad): scan for package name instead of assuming package at index 0
-//
-// idmap version 0x01 naively assumes that the package to use is always the first ResTable_package
-// in the resources.arsc blob. In most cases, there is only a single ResTable_package anyway, so
-// this assumption tends to work out. That said, the correct thing to do is to scan
-// resources.arsc for a package with a given name as read from the package manifest instead of
-// relying on a hard-coded index. This however requires storing the package name in the idmap
-// header, which in turn requires incrementing the idmap version. Because the initial version of
-// idmap2 is compatible with idmap, this will have to wait for now.
-const LoadedPackage* GetPackageAtIndex0(const LoadedArsc& loaded_arsc) {
-  const std::vector<std::unique_ptr<const LoadedPackage>>& packages = loaded_arsc.GetPackages();
-  if (packages.empty()) {
-    return nullptr;
-  }
-  int id = packages[0]->GetPackageId();
-  return loaded_arsc.GetPackageById(id);
-}
-
 Result<uint32_t> GetCrc(const ZipFile& zip) {
   const Result<uint32_t> a = zip.Crc("resources.arsc");
   const Result<uint32_t> b = zip.Crc("AndroidManifest.xml");
@@ -266,95 +241,57 @@
   return {std::move(idmap)};
 }
 
-std::string ConcatPolicies(const std::vector<std::string>& policies) {
-  std::string message;
-  for (const std::string& policy : policies) {
-    if (!message.empty()) {
-      message.append("|");
+Result<std::unique_ptr<const IdmapData>> IdmapData::FromResourceMapping(
+    const ResourceMapping& resource_mapping) {
+  if (resource_mapping.GetTargetToOverlayMap().empty()) {
+    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;
     }
-    message.append(policy);
+
+    matching_resources.Add(mapping.first, mapping.second.data_value);
   }
 
-  return message;
+  // 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));
+  }
+
+  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_ = std::move(data_header);
+  return {std::move(data)};
 }
 
-Result<Unit> CheckOverlayable(const LoadedPackage& target_package,
-                              const utils::OverlayManifestInfo& overlay_info,
-                              const PolicyBitmask& fulfilled_policies, const ResourceId& resid) {
-  static constexpr const PolicyBitmask sDefaultPolicies =
-      PolicyFlags::POLICY_ODM_PARTITION | PolicyFlags::POLICY_OEM_PARTITION |
-      PolicyFlags::POLICY_SYSTEM_PARTITION | PolicyFlags::POLICY_VENDOR_PARTITION |
-      PolicyFlags::POLICY_PRODUCT_PARTITION | PolicyFlags::POLICY_SIGNATURE;
-
-  // If the resource does not have an overlayable definition, allow the resource to be overlaid if
-  // the overlay is preinstalled or signed with the same signature as the target.
-  if (!target_package.DefinesOverlayable()) {
-    return (sDefaultPolicies & fulfilled_policies) != 0
-               ? Result<Unit>({})
-               : Error(
-                     "overlay must be preinstalled or signed with the same signature as the "
-                     "target");
-  }
-
-  const OverlayableInfo* overlayable_info = target_package.GetOverlayableInfo(resid);
-  if (overlayable_info == nullptr) {
-    // Do not allow non-overlayable resources to be overlaid.
-    return Error("resource has no overlayable declaration");
-  }
-
-  if (overlay_info.target_name != overlayable_info->name) {
-    // If the overlay supplies a target overlayable name, the resource must belong to the
-    // overlayable defined with the specified name to be overlaid.
-    return Error("<overlay> android:targetName '%s' does not match overlayable name '%s'",
-                 overlay_info.target_name.c_str(), overlayable_info->name.c_str());
-  }
-
-  // Enforce policy restrictions if the resource is declared as overlayable.
-  if ((overlayable_info->policy_flags & fulfilled_policies) == 0) {
-    return Error("overlay with policies '%s' does not fulfill any overlayable policies '%s'",
-                 ConcatPolicies(BitmaskToPolicies(fulfilled_policies)).c_str(),
-                 ConcatPolicies(BitmaskToPolicies(overlayable_info->policy_flags)).c_str());
-  }
-
-  return Result<Unit>({});
-}
-
-Result<std::unique_ptr<const Idmap>> Idmap::FromApkAssets(const std::string& target_apk_path,
-                                                          const ApkAssets& target_apk_assets,
-                                                          const std::string& overlay_apk_path,
+Result<std::unique_ptr<const Idmap>> Idmap::FromApkAssets(const ApkAssets& target_apk_assets,
                                                           const ApkAssets& overlay_apk_assets,
                                                           const PolicyBitmask& fulfilled_policies,
                                                           bool enforce_overlayable) {
   SYSTRACE << "Idmap::FromApkAssets";
-  AssetManager2 target_asset_manager;
-  if (!target_asset_manager.SetApkAssets({&target_apk_assets}, true, false)) {
-    return Error("failed to create target asset manager");
-  }
-
-  AssetManager2 overlay_asset_manager;
-  if (!overlay_asset_manager.SetApkAssets({&overlay_apk_assets}, true, false)) {
-    return Error("failed to create overlay asset manager");
-  }
-
-  const LoadedArsc* target_arsc = target_apk_assets.GetLoadedArsc();
-  if (target_arsc == nullptr) {
-    return Error("failed to load target resources.arsc");
-  }
-
-  const LoadedArsc* overlay_arsc = overlay_apk_assets.GetLoadedArsc();
-  if (overlay_arsc == nullptr) {
-    return Error("failed to load overlay resources.arsc");
-  }
-
-  const LoadedPackage* target_pkg = GetPackageAtIndex0(*target_arsc);
-  if (target_pkg == nullptr) {
-    return Error("failed to load target package from resources.arsc");
-  }
-
-  const LoadedPackage* overlay_pkg = GetPackageAtIndex0(*overlay_arsc);
-  if (overlay_pkg == nullptr) {
-    return Error("failed to load overlay package from resources.arsc");
-  }
+  const std::string& target_apk_path = target_apk_assets.GetPath();
+  const std::string& overlay_apk_path = overlay_apk_assets.GetPath();
 
   const std::unique_ptr<const ZipFile> target_zip = ZipFile::Open(target_apk_path);
   if (!target_zip) {
@@ -366,11 +303,6 @@
     return Error("failed to open overlay as zip");
   }
 
-  auto overlay_info = utils::ExtractOverlayManifestInfo(overlay_apk_path);
-  if (!overlay_info) {
-    return overlay_info.GetError();
-  }
-
   std::unique_ptr<IdmapHeader> header(new IdmapHeader());
   header->magic_ = kIdmapMagic;
   header->version_ = kIdmapCurrentVersion;
@@ -395,7 +327,7 @@
   memcpy(header->target_path_, target_apk_path.data(), target_apk_path.size());
 
   if (overlay_apk_path.size() > sizeof(header->overlay_path_)) {
-    return Error("overlay apk path \"%s\" longer than maximum size %zu", target_apk_path.c_str(),
+    return Error("overlay apk path \"%s\" longer than maximum size %zu", overlay_apk_path.c_str(),
                  sizeof(header->target_path_));
   }
   memset(header->overlay_path_, 0, sizeof(header->overlay_path_));
@@ -404,70 +336,24 @@
   std::unique_ptr<Idmap> idmap(new Idmap());
   idmap->header_ = std::move(header);
 
-  // find the resources that exist in both packages
-  MatchingResources matching_resources;
-  const auto end = overlay_pkg->end();
-  for (auto iter = overlay_pkg->begin(); iter != end; ++iter) {
-    const ResourceId overlay_resid = *iter;
-    Result<std::string> name = utils::ResToTypeEntryName(overlay_asset_manager, overlay_resid);
-    if (!name) {
-      continue;
-    }
-    // prepend "<package>:" to turn name into "<package>:<type>/<name>"
-    const std::string full_name =
-        base::StringPrintf("%s:%s", target_pkg->GetPackageName().c_str(), name->c_str());
-    const ResourceId target_resid = NameToResid(target_asset_manager, full_name);
-    if (target_resid == 0) {
-      continue;
-    }
-
-    if (enforce_overlayable) {
-      Result<Unit> success =
-          CheckOverlayable(*target_pkg, *overlay_info, fulfilled_policies, target_resid);
-      if (!success) {
-        LOG(WARNING) << "overlay \"" << overlay_apk_path
-                     << "\" is not allowed to overlay resource \"" << full_name
-                     << "\": " << success.GetErrorMessage();
-        continue;
-      }
-    }
-
-    matching_resources.Add(target_resid, overlay_resid);
+  auto overlay_info = utils::ExtractOverlayManifestInfo(overlay_apk_path);
+  if (!overlay_info) {
+    return overlay_info.GetError();
   }
 
-  if (matching_resources.Map().empty()) {
-    return Error("overlay \"%s\" does not successfully overlay any resource",
-                 overlay_apk_path.c_str());
+  auto resource_mapping =
+      ResourceMapping::FromApkAssets(target_apk_assets, overlay_apk_assets, *overlay_info,
+                                     fulfilled_policies, enforce_overlayable);
+  if (!resource_mapping) {
+    return resource_mapping.GetError();
   }
 
-  // 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));
+  auto idmap_data = IdmapData::FromResourceMapping(*resource_mapping);
+  if (!idmap_data) {
+    return idmap_data.GetError();
   }
 
-  std::unique_ptr<IdmapData::Header> data_header(new IdmapData::Header());
-  data_header->target_package_id_ = target_pkg->GetPackageId();
-  data_header->type_count_ = data->type_entries_.size();
-  data->header_ = std::move(data_header);
-
-  idmap->data_.push_back(std::move(data));
-
+  idmap->data_.push_back(std::move(*idmap_data));
   return {std::move(idmap)};
 }
 
diff --git a/cmds/idmap2/libidmap2/ResourceMapping.cpp b/cmds/idmap2/libidmap2/ResourceMapping.cpp
new file mode 100644
index 0000000..95ae626
--- /dev/null
+++ b/cmds/idmap2/libidmap2/ResourceMapping.cpp
@@ -0,0 +1,411 @@
+/*
+ * 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 "idmap2/ResourceMapping.h"
+
+#include <map>
+#include <memory>
+#include <set>
+#include <string>
+#include <utility>
+#include <vector>
+
+#include "android-base/stringprintf.h"
+#include "idmap2/ResourceUtils.h"
+
+using android::base::StringPrintf;
+using android::idmap2::utils::ResToTypeEntryName;
+
+namespace android::idmap2 {
+
+namespace {
+
+#define EXTRACT_PACKAGE(resid) ((0xff000000 & (resid)) >> 24)
+
+std::string ConcatPolicies(const std::vector<std::string>& policies) {
+  std::string message;
+  for (const std::string& policy : policies) {
+    if (!message.empty()) {
+      message.append("|");
+    }
+    message.append(policy);
+  }
+
+  return message;
+}
+
+Result<Unit> CheckOverlayable(const LoadedPackage& target_package,
+                              const OverlayManifestInfo& overlay_info,
+                              const PolicyBitmask& fulfilled_policies,
+                              const ResourceId& target_resource) {
+  static constexpr const PolicyBitmask sDefaultPolicies =
+      PolicyFlags::POLICY_ODM_PARTITION | PolicyFlags::POLICY_OEM_PARTITION |
+      PolicyFlags::POLICY_SYSTEM_PARTITION | PolicyFlags::POLICY_VENDOR_PARTITION |
+      PolicyFlags::POLICY_PRODUCT_PARTITION | PolicyFlags::POLICY_SIGNATURE;
+
+  // If the resource does not have an overlayable definition, allow the resource to be overlaid if
+  // the overlay is preinstalled or signed with the same signature as the target.
+  if (!target_package.DefinesOverlayable()) {
+    return (sDefaultPolicies & fulfilled_policies) != 0
+               ? Result<Unit>({})
+               : Error(
+                     "overlay must be preinstalled or signed with the same signature as the "
+                     "target");
+  }
+
+  const OverlayableInfo* overlayable_info = target_package.GetOverlayableInfo(target_resource);
+  if (overlayable_info == nullptr) {
+    // Do not allow non-overlayable resources to be overlaid.
+    return Error("target resource has no overlayable declaration");
+  }
+
+  if (overlay_info.target_name != overlayable_info->name) {
+    // If the overlay supplies a target overlayable name, the resource must belong to the
+    // overlayable defined with the specified name to be overlaid.
+    return Error(R"(<overlay> android:targetName "%s" does not match overlayable name "%s")",
+                 overlay_info.target_name.c_str(), overlayable_info->name.c_str());
+  }
+
+  // Enforce policy restrictions if the resource is declared as overlayable.
+  if ((overlayable_info->policy_flags & fulfilled_policies) == 0) {
+    return Error(R"(overlay with policies "%s" does not fulfill any overlayable policies "%s")",
+                 ConcatPolicies(BitmaskToPolicies(fulfilled_policies)).c_str(),
+                 ConcatPolicies(BitmaskToPolicies(overlayable_info->policy_flags)).c_str());
+  }
+
+  return Result<Unit>({});
+}
+
+// TODO(martenkongstad): scan for package name instead of assuming package at index 0
+//
+// idmap version 0x01 naively assumes that the package to use is always the first ResTable_package
+// in the resources.arsc blob. In most cases, there is only a single ResTable_package anyway, so
+// this assumption tends to work out. That said, the correct thing to do is to scan
+// resources.arsc for a package with a given name as read from the package manifest instead of
+// relying on a hard-coded index. This however requires storing the package name in the idmap
+// header, which in turn requires incrementing the idmap version. Because the initial version of
+// idmap2 is compatible with idmap, this will have to wait for now.
+const LoadedPackage* GetPackageAtIndex0(const LoadedArsc& loaded_arsc) {
+  const std::vector<std::unique_ptr<const LoadedPackage>>& packages = loaded_arsc.GetPackages();
+  if (packages.empty()) {
+    return nullptr;
+  }
+  int id = packages[0]->GetPackageId();
+  return loaded_arsc.GetPackageById(id);
+}
+
+Result<std::unique_ptr<Asset>> OpenNonAssetFromResource(const ResourceId& resource_id,
+                                                        const AssetManager2& asset_manager) {
+  Res_value value{};
+  ResTable_config selected_config{};
+  uint32_t flags;
+  auto cookie =
+      asset_manager.GetResource(resource_id, /* may_be_bag */ false,
+                                /* density_override */ 0U, &value, &selected_config, &flags);
+  if (cookie == kInvalidCookie) {
+    return Error("failed to find resource for id 0x%08x", resource_id);
+  }
+
+  if (value.dataType != Res_value::TYPE_STRING) {
+    return Error("resource for is 0x%08x is not a file", resource_id);
+  }
+
+  auto string_pool = asset_manager.GetStringPoolForCookie(cookie);
+  size_t len;
+  auto file_path16 = string_pool->stringAt(value.data, &len);
+  if (file_path16 == nullptr) {
+    return Error("failed to find string for index %d", value.data);
+  }
+
+  // Load the overlay resource mappings from the file specified using android:resourcesMap.
+  auto file_path = String8(String16(file_path16));
+  auto asset = asset_manager.OpenNonAsset(file_path.c_str(), Asset::AccessMode::ACCESS_BUFFER);
+  if (asset == nullptr) {
+    return Error("file \"%s\" not found", file_path.c_str());
+  }
+
+  return asset;
+}
+
+}  // namespace
+
+Result<ResourceMapping> ResourceMapping::CreateResourceMapping(const AssetManager2* target_am,
+                                                               const LoadedPackage* target_package,
+                                                               const LoadedPackage* overlay_package,
+                                                               size_t string_pool_offset,
+                                                               const XmlParser& overlay_parser) {
+  ResourceMapping resource_mapping;
+  auto root_it = overlay_parser.tree_iterator();
+  if (root_it->event() != XmlParser::Event::START_TAG || root_it->name() != "overlay") {
+    return Error("root element is not <overlay> tag");
+  }
+
+  const uint8_t overlay_package_id = overlay_package->GetPackageId();
+  auto overlay_it_end = root_it.end();
+  for (auto overlay_it = root_it.begin(); overlay_it != overlay_it_end; ++overlay_it) {
+    if (overlay_it->event() == XmlParser::Event::BAD_DOCUMENT) {
+      return Error("failed to parse overlay xml document");
+    }
+
+    if (overlay_it->event() != XmlParser::Event::START_TAG) {
+      continue;
+    }
+
+    if (overlay_it->name() != "item") {
+      return Error("unexpected tag <%s> in <overlay>", overlay_it->name().c_str());
+    }
+
+    Result<std::string> target_resource = overlay_it->GetAttributeStringValue("target");
+    if (!target_resource) {
+      return Error(R"(<item> tag missing expected attribute "target")");
+    }
+
+    Result<android::Res_value> overlay_resource = overlay_it->GetAttributeValue("value");
+    if (!overlay_resource) {
+      return Error(R"(<item> tag missing expected attribute "value")");
+    }
+
+    ResourceId target_id =
+        target_am->GetResourceId(*target_resource, "", target_package->GetPackageName());
+    if (target_id == 0U) {
+      LOG(WARNING) << "failed to find resource \"" << *target_resource << "\" in target resources";
+      continue;
+    }
+
+    if (overlay_resource->dataType == Res_value::TYPE_STRING) {
+      overlay_resource->data += string_pool_offset;
+    }
+
+    // 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_package_id == EXTRACT_PACKAGE(overlay_resource->data)
+            : false;
+
+    resource_mapping.AddMapping(target_id, overlay_resource->dataType, overlay_resource->data,
+                                rewrite_overlay_reference);
+  }
+
+  return resource_mapping;
+}
+
+Result<ResourceMapping> ResourceMapping::CreateResourceMappingLegacy(
+    const AssetManager2* target_am, const AssetManager2* overlay_am,
+    const LoadedPackage* target_package, const LoadedPackage* overlay_package) {
+  ResourceMapping resource_mapping;
+  const auto end = overlay_package->end();
+  for (auto iter = overlay_package->begin(); iter != end; ++iter) {
+    const ResourceId overlay_resid = *iter;
+    Result<std::string> name = utils::ResToTypeEntryName(*overlay_am, overlay_resid);
+    if (!name) {
+      continue;
+    }
+
+    // Find the resource with the same type and entry name within the target package.
+    const std::string full_name =
+        base::StringPrintf("%s:%s", target_package->GetPackageName().c_str(), name->c_str());
+    const ResourceId target_resource = target_am->GetResourceId(full_name);
+    if (target_resource == 0U) {
+      continue;
+    }
+
+    resource_mapping.AddMapping(target_resource, Res_value::TYPE_REFERENCE, overlay_resid,
+                                /* rewrite_overlay_reference */ true);
+  }
+
+  return resource_mapping;
+}
+
+void ResourceMapping::FilterOverlayableResources(const AssetManager2* target_am,
+                                                 const LoadedPackage* target_package,
+                                                 const LoadedPackage* overlay_package,
+                                                 const OverlayManifestInfo& overlay_info,
+                                                 const PolicyBitmask& fulfilled_policies) {
+  std::set<ResourceId> remove_ids;
+  for (const auto& target_map : target_map_) {
+    const ResourceId target_resid = target_map.first;
+    Result<Unit> success =
+        CheckOverlayable(*target_package, overlay_info, fulfilled_policies, target_resid);
+    if (success) {
+      continue;
+    }
+
+    // Attempting to overlay a resource that is not allowed to be overlaid is treated as a
+    // warning.
+    Result<std::string> name = utils::ResToTypeEntryName(*target_am, target_resid);
+    if (!name) {
+      name = StringPrintf("0x%08x", target_resid);
+    }
+
+    LOG(WARNING) << "overlay \"" << overlay_package->GetPackageName()
+                 << "\" is not allowed to overlay resource \"" << *name
+                 << "\" in target: " << success.GetErrorMessage();
+
+    remove_ids.insert(target_resid);
+  }
+
+  for (const ResourceId target_resid : remove_ids) {
+    RemoveMapping(target_resid);
+  }
+}
+
+Result<ResourceMapping> ResourceMapping::FromApkAssets(const ApkAssets& target_apk_assets,
+                                                       const ApkAssets& overlay_apk_assets,
+                                                       const OverlayManifestInfo& overlay_info,
+                                                       const PolicyBitmask& fulfilled_policies,
+                                                       bool enforce_overlayable) {
+  AssetManager2 target_asset_manager;
+  if (!target_asset_manager.SetApkAssets({&target_apk_assets}, true /* invalidate_caches */,
+                                         false /* filter_incompatible_configs*/)) {
+    return Error("failed to create target asset manager");
+  }
+
+  AssetManager2 overlay_asset_manager;
+  if (!overlay_asset_manager.SetApkAssets({&overlay_apk_assets}, true /* invalidate_caches */,
+                                          false /* filter_incompatible_configs */)) {
+    return Error("failed to create overlay asset manager");
+  }
+
+  const LoadedArsc* target_arsc = target_apk_assets.GetLoadedArsc();
+  if (target_arsc == nullptr) {
+    return Error("failed to load target resources.arsc");
+  }
+
+  const LoadedArsc* overlay_arsc = overlay_apk_assets.GetLoadedArsc();
+  if (overlay_arsc == nullptr) {
+    return Error("failed to load overlay resources.arsc");
+  }
+
+  const LoadedPackage* target_pkg = GetPackageAtIndex0(*target_arsc);
+  if (target_pkg == nullptr) {
+    return Error("failed to load target package from resources.arsc");
+  }
+
+  const LoadedPackage* overlay_pkg = GetPackageAtIndex0(*overlay_arsc);
+  if (overlay_pkg == nullptr) {
+    return Error("failed to load overlay package from resources.arsc");
+  }
+
+  size_t string_pool_data_length = 0U;
+  size_t string_pool_offset = 0U;
+  std::unique_ptr<uint8_t[]> string_pool_data;
+  Result<ResourceMapping> resource_mapping = {{}};
+  if (overlay_info.resource_mapping != 0U) {
+    // Load the overlay resource mappings from the file specified using android:resourcesMap.
+    auto asset = OpenNonAssetFromResource(overlay_info.resource_mapping, overlay_asset_manager);
+    if (!asset) {
+      return Error("failed opening xml for android:resourcesMap: %s",
+                   asset.GetErrorMessage().c_str());
+    }
+
+    auto parser =
+        XmlParser::Create((*asset)->getBuffer(true /* wordAligned*/), (*asset)->getLength());
+    if (!parser) {
+      return Error("failed opening ResXMLTree");
+    }
+
+    // Copy the xml string pool data before the parse goes out of scope.
+    auto& string_pool = (*parser)->get_strings();
+    string_pool_data_length = string_pool.bytes();
+    string_pool_data.reset(new uint8_t[string_pool_data_length]);
+    memcpy(string_pool_data.get(), string_pool.data(), string_pool_data_length);
+
+    // Offset string indices by the size of the overlay resource table string pool.
+    string_pool_offset = overlay_arsc->GetStringPool()->size();
+
+    resource_mapping = CreateResourceMapping(&target_asset_manager, target_pkg, overlay_pkg,
+                                             string_pool_offset, *(*parser));
+  } else {
+    // If no file is specified using android:resourcesMap, it is assumed that the overlay only
+    // defines resources intended to override target resources of the same type and name.
+    resource_mapping = CreateResourceMappingLegacy(&target_asset_manager, &overlay_asset_manager,
+                                                   target_pkg, overlay_pkg);
+  }
+
+  if (!resource_mapping) {
+    return resource_mapping.GetError();
+  }
+
+  if (enforce_overlayable) {
+    // Filter out resources the overlay is not allowed to override.
+    (*resource_mapping)
+        .FilterOverlayableResources(&target_asset_manager, target_pkg, overlay_pkg, overlay_info,
+                                    fulfilled_policies);
+  }
+
+  resource_mapping->target_package_id_ = target_pkg->GetPackageId();
+  resource_mapping->overlay_package_id_ = overlay_pkg->GetPackageId();
+  resource_mapping->string_pool_offset_ = string_pool_offset;
+  resource_mapping->string_pool_data_ = std::move(string_pool_data);
+  resource_mapping->string_pool_data_length_ = string_pool_data_length;
+  return std::move(*resource_mapping);
+}
+
+OverlayResourceMap ResourceMapping::GetOverlayToTargetMap() const {
+  // An overlay resource can override multiple target resources at once. Rewrite the overlay
+  // resource as the first target resource it overrides.
+  OverlayResourceMap map;
+  for (const auto& mappings : overlay_map_) {
+    map.insert(std::make_pair(mappings.first, mappings.second));
+  }
+  return map;
+}
+
+Result<Unit> ResourceMapping::AddMapping(ResourceId target_resource,
+                                         TargetValue::DataType data_type,
+                                         TargetValue::DataValue data_value,
+                                         bool rewrite_overlay_reference) {
+  if (target_map_.find(target_resource) != target_map_.end()) {
+    return Error(R"(target resource id "0x%08x" mapped to multiple values)", target_resource);
+  }
+
+  // TODO(141485591): Ensure that the overlay type is compatible with the target type. If the
+  // runtime types are not compatible, it could cause runtime crashes when the resource is resolved.
+
+  target_map_.insert(std::make_pair(target_resource, TargetValue{data_type, data_value}));
+
+  if (rewrite_overlay_reference && data_type == Res_value::TYPE_REFERENCE) {
+    overlay_map_.insert(std::make_pair(data_value, target_resource));
+  }
+
+  return Result<Unit>({});
+}
+
+void ResourceMapping::RemoveMapping(ResourceId target_resource) {
+  auto target_iter = target_map_.find(target_resource);
+  if (target_iter == target_map_.end()) {
+    return;
+  }
+
+  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) {
+    return;
+  }
+
+  auto overlay_iter = overlay_map_.equal_range(value.data_value);
+  for (auto i = overlay_iter.first; i != overlay_iter.second; ++i) {
+    if (i->second == target_resource) {
+      overlay_map_.erase(i);
+      return;
+    }
+  }
+}
+
+}  // namespace android::idmap2
diff --git a/cmds/idmap2/libidmap2/ResourceUtils.cpp b/cmds/idmap2/libidmap2/ResourceUtils.cpp
index dce83e3..9d32692 100644
--- a/cmds/idmap2/libidmap2/ResourceUtils.cpp
+++ b/cmds/idmap2/libidmap2/ResourceUtils.cpp
@@ -22,18 +22,18 @@
 #include "androidfw/StringPiece.h"
 #include "androidfw/Util.h"
 #include "idmap2/Result.h"
-#include "idmap2/Xml.h"
+#include "idmap2/XmlParser.h"
 #include "idmap2/ZipFile.h"
 
 using android::StringPiece16;
 using android::idmap2::Result;
-using android::idmap2::Xml;
+using android::idmap2::XmlParser;
 using android::idmap2::ZipFile;
 using android::util::Utf16ToUtf8;
 
 namespace android::idmap2::utils {
 
-Result<std::string> ResToTypeEntryName(const AssetManager2& am, ResourceId resid) {
+Result<std::string> ResToTypeEntryName(const AssetManager2& am, uint32_t resid) {
   AssetManager2::ResourceName name;
   if (!am.GetResourceName(resid, &name)) {
     return Error("no resource 0x%08x in asset manager", resid);
@@ -65,52 +65,72 @@
     return Error("failed to uncompress AndroidManifest.xml from %s", path.c_str());
   }
 
-  std::unique_ptr<const Xml> xml = Xml::Create(entry->buf, entry->size);
+  Result<std::unique_ptr<const XmlParser>> xml = XmlParser::Create(entry->buf, entry->size);
   if (!xml) {
     return Error("failed to parse AndroidManifest.xml from %s", path.c_str());
   }
 
+  auto manifest_it = (*xml)->tree_iterator();
+  if (manifest_it->event() != XmlParser::Event::START_TAG || manifest_it->name() != "manifest") {
+    return Error("root element tag is not <manifest> in AndroidManifest.xml of %s", path.c_str());
+  }
+
+  auto overlay_it = std::find_if(manifest_it.begin(), manifest_it.end(), [](const auto& it) {
+    return it.event() == XmlParser::Event::START_TAG && it.name() == "overlay";
+  });
+
   OverlayManifestInfo info{};
-  const auto tag = xml->FindTag("overlay");
-  if (!tag) {
-    if (assert_overlay) {
-      return Error("<overlay> missing from AndroidManifest.xml of %s", path.c_str());
+  if (overlay_it == manifest_it.end()) {
+    if (!assert_overlay) {
+      return info;
     }
-    return info;
+    return Error("<overlay> missing from AndroidManifest.xml of %s", path.c_str());
   }
 
-  auto iter = tag->find("targetPackage");
-  if (iter == tag->end()) {
-    if (assert_overlay) {
-      return Error("android:targetPackage missing from <overlay> of %s", path.c_str());
-    }
+  if (auto result_str = overlay_it->GetAttributeStringValue("targetPackage")) {
+    info.target_package = *result_str;
   } else {
-    info.target_package = iter->second;
+    return Error("android:targetPackage missing from <overlay> of %s: %s", path.c_str(),
+                 result_str.GetErrorMessage().c_str());
   }
 
-  iter = tag->find("targetName");
-  if (iter != tag->end()) {
-    info.target_name = iter->second;
+  if (auto result_str = overlay_it->GetAttributeStringValue("targetName")) {
+    info.target_name = *result_str;
   }
 
-  iter = tag->find("isStatic");
-  if (iter != tag->end()) {
-    info.is_static = std::stoul(iter->second) != 0U;
+  if (auto result_value = overlay_it->GetAttributeValue("resourcesMap")) {
+    if ((*result_value).dataType == Res_value::TYPE_REFERENCE) {
+      info.resource_mapping = (*result_value).data;
+    } else {
+      return Error("android:resourcesMap is not a reference in AndroidManifest.xml of %s",
+                   path.c_str());
+    }
   }
 
-  iter = tag->find("priority");
-  if (iter != tag->end()) {
-    info.priority = std::stoi(iter->second);
+  if (auto result_value = overlay_it->GetAttributeValue("isStatic")) {
+    if ((*result_value).dataType >= Res_value::TYPE_FIRST_INT &&
+        (*result_value).dataType <= Res_value::TYPE_LAST_INT) {
+      info.is_static = (*result_value).data != 0U;
+    } else {
+      return Error("android:isStatic is not a boolean in AndroidManifest.xml of %s", path.c_str());
+    }
   }
 
-  iter = tag->find("requiredSystemPropertyName");
-  if (iter != tag->end()) {
-    info.requiredSystemPropertyName = iter->second;
+  if (auto result_value = overlay_it->GetAttributeValue("priority")) {
+    if ((*result_value).dataType >= Res_value::TYPE_FIRST_INT &&
+        (*result_value).dataType <= Res_value::TYPE_LAST_INT) {
+      info.priority = (*result_value).data;
+    } else {
+      return Error("android:priority is not an integer in AndroidManifest.xml of %s", path.c_str());
+    }
   }
 
-  iter = tag->find("requiredSystemPropertyValue");
-  if (iter != tag->end()) {
-    info.requiredSystemPropertyValue = iter->second;
+  if (auto result_str = overlay_it->GetAttributeStringValue("requiredSystemPropertyName")) {
+    info.requiredSystemPropertyName = *result_str;
+  }
+
+   if (auto result_str = overlay_it->GetAttributeStringValue("requiredSystemPropertyValue")) {
+    info.requiredSystemPropertyValue = *result_str;
   }
 
   return info;
diff --git a/cmds/idmap2/libidmap2/Xml.cpp b/cmds/idmap2/libidmap2/Xml.cpp
deleted file mode 100644
index 2645868..0000000
--- a/cmds/idmap2/libidmap2/Xml.cpp
+++ /dev/null
@@ -1,80 +0,0 @@
-/*
- * Copyright (C) 2018 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include "idmap2/Xml.h"
-
-#include <map>
-#include <memory>
-#include <string>
-#include <utility>
-
-namespace android::idmap2 {
-
-std::unique_ptr<const Xml> Xml::Create(const uint8_t* data, size_t size, bool copyData) {
-  std::unique_ptr<Xml> xml(new Xml());
-  if (xml->xml_.setTo(data, size, copyData) != NO_ERROR) {
-    return nullptr;
-  }
-  return xml;
-}
-
-std::unique_ptr<std::map<std::string, std::string>> Xml::FindTag(const std::string& name) const {
-  const String16 tag_to_find(name.c_str(), name.size());
-  xml_.restart();
-  ResXMLParser::event_code_t type;
-  do {
-    type = xml_.next();
-    if (type == ResXMLParser::START_TAG) {
-      size_t len;
-      const String16 tag(xml_.getElementName(&len));
-      if (tag == tag_to_find) {
-        std::unique_ptr<std::map<std::string, std::string>> map(
-            new std::map<std::string, std::string>());
-        for (size_t i = 0; i < xml_.getAttributeCount(); i++) {
-          const String16 key16(xml_.getAttributeName(i, &len));
-          std::string key = String8(key16).c_str();
-
-          std::string value;
-          switch (xml_.getAttributeDataType(i)) {
-            case Res_value::TYPE_STRING: {
-              const String16 value16(xml_.getAttributeStringValue(i, &len));
-              value = String8(value16).c_str();
-            } break;
-            case Res_value::TYPE_INT_DEC:
-            case Res_value::TYPE_INT_HEX:
-            case Res_value::TYPE_INT_BOOLEAN: {
-              Res_value resValue;
-              xml_.getAttributeValue(i, &resValue);
-              value = std::to_string(resValue.data);
-            } break;
-            default:
-              return nullptr;
-          }
-
-          map->emplace(std::make_pair(key, value));
-        }
-        return map;
-      }
-    }
-  } while (type != ResXMLParser::BAD_DOCUMENT && type != ResXMLParser::END_DOCUMENT);
-  return nullptr;
-}
-
-Xml::~Xml() {
-  xml_.uninit();
-}
-
-}  // namespace android::idmap2
diff --git a/cmds/idmap2/libidmap2/XmlParser.cpp b/cmds/idmap2/libidmap2/XmlParser.cpp
new file mode 100644
index 0000000..526a560
--- /dev/null
+++ b/cmds/idmap2/libidmap2/XmlParser.cpp
@@ -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.
+ */
+
+#include "idmap2/XmlParser.h"
+
+#include <iostream>
+#include <map>
+#include <memory>
+#include <string>
+#include <utility>
+
+namespace android::idmap2 {
+
+template <typename T>
+ResXMLParser::ResXMLPosition get_tree_position(const T& tree) {
+  ResXMLParser::ResXMLPosition pos{};
+  tree.getPosition(&pos);
+  return pos;
+}
+
+XmlParser::Node::Node(const ResXMLTree& tree) : Node(tree, get_tree_position(tree)) {
+}
+XmlParser::Node::Node(const ResXMLTree& tree, const ResXMLParser::ResXMLPosition& pos)
+    : parser_(tree) {
+  set_position(pos);
+}
+
+bool XmlParser::Node::operator==(const XmlParser::Node& rhs) const {
+  ResXMLParser::ResXMLPosition pos = get_position();
+  ResXMLParser::ResXMLPosition rhs_pos = rhs.get_position();
+  return pos.curExt == rhs_pos.curExt && pos.curNode == rhs_pos.curNode &&
+         pos.eventCode == rhs_pos.eventCode;
+}
+
+bool XmlParser::Node::operator!=(const XmlParser::Node& rhs) const {
+  return !(*this == rhs);
+}
+
+ResXMLParser::ResXMLPosition XmlParser::Node::get_position() const {
+  return get_tree_position(parser_);
+}
+
+void XmlParser::Node::set_position(const ResXMLParser::ResXMLPosition& pos) {
+  parser_.setPosition(pos);
+}
+
+bool XmlParser::Node::Seek(bool inner_child) {
+  if (parser_.getEventType() == XmlParser::Event::END_TAG) {
+    return false;
+  }
+
+  ssize_t depth = 0;
+  XmlParser::Event code;
+  while ((code = parser_.next()) != XmlParser::Event::BAD_DOCUMENT &&
+         code != XmlParser::Event::END_DOCUMENT) {
+    if (code == XmlParser::Event::START_TAG) {
+      if (++depth == (inner_child ? 1 : 0)) {
+        return true;
+      }
+    } else if (code == XmlParser::Event::END_TAG) {
+      if (--depth == (inner_child ? -1 : -2)) {
+        return false;
+      }
+    }
+  }
+
+  return false;
+}
+
+XmlParser::Event XmlParser::Node::event() const {
+  return parser_.getEventType();
+}
+
+std::string XmlParser::Node::name() const {
+  size_t len;
+  const String16 key16(parser_.getElementName(&len));
+  return String8(key16).c_str();
+}
+
+Result<std::string> XmlParser::Node::GetAttributeStringValue(const std::string& name) const {
+  auto value = GetAttributeValue(name);
+  if (!value) {
+    return value.GetError();
+  }
+
+  switch ((*value).dataType) {
+    case Res_value::TYPE_STRING: {
+      size_t len;
+      const String16 value16(parser_.getStrings().stringAt((*value).data, &len));
+      return std::string(String8(value16).c_str());
+    }
+    case Res_value::TYPE_INT_DEC:
+    case Res_value::TYPE_INT_HEX:
+    case Res_value::TYPE_INT_BOOLEAN: {
+      return std::to_string((*value).data);
+    }
+    default:
+      return Error(R"(Failed to convert attribute "%s" value to a string)", name.c_str());
+  }
+}
+
+Result<Res_value> XmlParser::Node::GetAttributeValue(const std::string& name) const {
+  size_t len;
+  for (size_t i = 0; i < parser_.getAttributeCount(); i++) {
+    const String16 key16(parser_.getAttributeName(i, &len));
+    std::string key = String8(key16).c_str();
+    if (key != name) {
+      continue;
+    }
+
+    Res_value res_value{};
+    if (parser_.getAttributeValue(i, &res_value) == BAD_TYPE) {
+      return Error(R"(Bad value for attribute "%s")", name.c_str());
+    }
+
+    return res_value;
+  }
+
+  return Error(R"(Failed to find attribute "%s")", name.c_str());
+}
+
+Result<std::unique_ptr<const XmlParser>> XmlParser::Create(const void* data, size_t size,
+                                                           bool copy_data) {
+  auto parser = std::unique_ptr<const XmlParser>(new XmlParser());
+  if (parser->tree_.setTo(data, size, copy_data) != NO_ERROR) {
+    return Error("Malformed xml block");
+  }
+
+  // Find the beginning of the first tag.
+  XmlParser::Event event;
+  while ((event = parser->tree_.next()) != XmlParser::Event::BAD_DOCUMENT &&
+         event != XmlParser::Event::END_DOCUMENT && event != XmlParser::Event::START_TAG) {
+  }
+
+  if (event == XmlParser::Event::END_DOCUMENT) {
+    return Error("Root tag was not be found");
+  }
+
+  if (event == XmlParser::Event::BAD_DOCUMENT) {
+    return Error("Bad xml document");
+  }
+
+  return parser;
+}
+
+XmlParser::~XmlParser() {
+  tree_.uninit();
+}
+
+}  // namespace android::idmap2
diff --git a/cmds/idmap2/tests/BinaryStreamVisitorTests.cpp b/cmds/idmap2/tests/BinaryStreamVisitorTests.cpp
index 9348ab7..43fdc9a 100644
--- a/cmds/idmap2/tests/BinaryStreamVisitorTests.cpp
+++ b/cmds/idmap2/tests/BinaryStreamVisitorTests.cpp
@@ -75,9 +75,8 @@
   std::unique_ptr<const ApkAssets> overlay_apk = ApkAssets::Load(overlay_apk_path);
   ASSERT_THAT(overlay_apk, NotNull());
 
-  const auto idmap =
-      Idmap::FromApkAssets(target_apk_path, *target_apk, overlay_apk_path, *overlay_apk,
-                           PolicyFlags::POLICY_PUBLIC, /* enforce_overlayable */ true);
+  const auto idmap = Idmap::FromApkAssets(*target_apk, *overlay_apk, PolicyFlags::POLICY_PUBLIC,
+                                          /* enforce_overlayable */ true);
   ASSERT_TRUE(idmap);
 
   std::stringstream stream;
diff --git a/cmds/idmap2/tests/IdmapTests.cpp b/cmds/idmap2/tests/IdmapTests.cpp
index 0f47f1e..47e5b17 100644
--- a/cmds/idmap2/tests/IdmapTests.cpp
+++ b/cmds/idmap2/tests/IdmapTests.cpp
@@ -179,8 +179,7 @@
   ASSERT_THAT(overlay_apk, NotNull());
 
   auto result =
-      Idmap::FromApkAssets(target_apk_path.to_string(), *target_apk, overlay_apk_path.to_string(),
-                           *overlay_apk, fulfilled_policies, enforce_overlayable);
+      Idmap::FromApkAssets(*target_apk, *overlay_apk, fulfilled_policies, enforce_overlayable);
   *out_idmap = result ? std::move(*result) : nullptr;
 }
 
@@ -195,7 +194,7 @@
   ASSERT_EQ(idmap->GetHeader()->GetMagic(), 0x504d4449U);
   ASSERT_EQ(idmap->GetHeader()->GetVersion(), 0x01U);
   ASSERT_EQ(idmap->GetHeader()->GetTargetCrc(), 0x76a20829);
-  ASSERT_EQ(idmap->GetHeader()->GetOverlayCrc(), 0x8635c2ed);
+  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);
@@ -480,9 +479,8 @@
   std::unique_ptr<const ApkAssets> overlay_apk = ApkAssets::Load(overlay_apk_path);
   ASSERT_THAT(overlay_apk, NotNull());
 
-  const auto result =
-      Idmap::FromApkAssets(target_apk_path, *target_apk, overlay_apk_path, *overlay_apk,
-                           PolicyFlags::POLICY_PUBLIC, /* enforce_overlayable */ true);
+  const auto result = Idmap::FromApkAssets(*target_apk, *overlay_apk, PolicyFlags::POLICY_PUBLIC,
+                                           /* enforce_overlayable */ true);
   ASSERT_FALSE(result);
 }
 
@@ -497,8 +495,7 @@
   std::unique_ptr<const ApkAssets> overlay_apk = ApkAssets::Load(overlay_apk_path);
   ASSERT_THAT(overlay_apk, NotNull());
 
-  auto result = Idmap::FromApkAssets(target_apk_path, *target_apk, overlay_apk_path, *overlay_apk,
-                                     PolicyFlags::POLICY_PUBLIC,
+  auto result = Idmap::FromApkAssets(*target_apk, *overlay_apk, PolicyFlags::POLICY_PUBLIC,
                                      /* enforce_overlayable */ true);
   ASSERT_TRUE(result);
   const auto idmap = std::move(*result);
diff --git a/cmds/idmap2/tests/PrettyPrintVisitorTests.cpp b/cmds/idmap2/tests/PrettyPrintVisitorTests.cpp
index c412504..1d34e42 100644
--- a/cmds/idmap2/tests/PrettyPrintVisitorTests.cpp
+++ b/cmds/idmap2/tests/PrettyPrintVisitorTests.cpp
@@ -43,9 +43,8 @@
   std::unique_ptr<const ApkAssets> overlay_apk = ApkAssets::Load(overlay_apk_path);
   ASSERT_THAT(overlay_apk, NotNull());
 
-  const auto idmap =
-      Idmap::FromApkAssets(target_apk_path, *target_apk, overlay_apk_path, *overlay_apk,
-                           PolicyFlags::POLICY_PUBLIC, /* enforce_overlayable */ true);
+  const auto idmap = Idmap::FromApkAssets(*target_apk, *overlay_apk, PolicyFlags::POLICY_PUBLIC,
+                                          /* enforce_overlayable */ true);
   ASSERT_TRUE(idmap);
 
   std::stringstream stream;
diff --git a/cmds/idmap2/tests/RawPrintVisitorTests.cpp b/cmds/idmap2/tests/RawPrintVisitorTests.cpp
index 2695176..c243d74 100644
--- a/cmds/idmap2/tests/RawPrintVisitorTests.cpp
+++ b/cmds/idmap2/tests/RawPrintVisitorTests.cpp
@@ -38,9 +38,8 @@
   std::unique_ptr<const ApkAssets> overlay_apk = ApkAssets::Load(overlay_apk_path);
   ASSERT_THAT(overlay_apk, NotNull());
 
-  const auto idmap =
-      Idmap::FromApkAssets(target_apk_path, *target_apk, overlay_apk_path, *overlay_apk,
-                           PolicyFlags::POLICY_PUBLIC, /* enforce_overlayable */ true);
+  const auto idmap = Idmap::FromApkAssets(*target_apk, *overlay_apk, PolicyFlags::POLICY_PUBLIC,
+                                          /* enforce_overlayable */ true);
   ASSERT_TRUE(idmap);
 
   std::stringstream stream;
@@ -50,7 +49,7 @@
   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("00000008: 76a20829  target crc\n"), std::string::npos);
-  ASSERT_NE(stream.str().find("0000000c: 8635c2ed  overlay 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"),
             std::string::npos);
 }
diff --git a/cmds/idmap2/tests/ResourceMappingTests.cpp b/cmds/idmap2/tests/ResourceMappingTests.cpp
new file mode 100644
index 0000000..1ef41de
--- /dev/null
+++ b/cmds/idmap2/tests/ResourceMappingTests.cpp
@@ -0,0 +1,322 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <cstdio>  // fclose
+#include <fstream>
+#include <memory>
+#include <sstream>
+#include <string>
+#include <utility>
+#include <vector>
+
+#include "TestHelpers.h"
+#include "gmock/gmock.h"
+#include "gtest/gtest.h"
+#include "idmap2/ResourceMapping.h"
+
+using android::idmap2::utils::ExtractOverlayManifestInfo;
+
+namespace android::idmap2 {
+
+#define ASSERT_RESULT(r)                             \
+  do {                                               \
+    auto result = r;                                 \
+    ASSERT_TRUE(result) << result.GetErrorMessage(); \
+  } while (0)
+
+Result<ResourceMapping> TestGetResourceMapping(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());
+  }
+
+  return ResourceMapping::FromApkAssets(*target_apk, *overlay_apk, overlay_info, fulfilled_policies,
+                                        enforce_overlayable);
+}
+
+Result<ResourceMapping> TestGetResourceMapping(const android::StringPiece& local_target_apk_path,
+                                               const android::StringPiece& local_overlay_apk_path,
+                                               const PolicyBitmask& fulfilled_policies,
+                                               bool enforce_overlayable) {
+  auto overlay_info = ExtractOverlayManifestInfo(GetTestDataPath() + local_overlay_apk_path.data());
+  if (!overlay_info) {
+    return overlay_info.GetError();
+  }
+  return TestGetResourceMapping(local_target_apk_path, local_overlay_apk_path, *overlay_info,
+                                fulfilled_policies, enforce_overlayable);
+}
+
+Result<Unit> MappingExists(const ResourceMapping& mapping, const ResourceId& target_resource,
+                           const uint8_t type, const uint32_t value, bool rewrite) {
+  auto target_map = mapping.GetTargetToOverlayMap();
+  auto entry_map = target_map.find(target_resource);
+  if (entry_map == target_map.end()) {
+    return Error("Failed to find mapping for target resource");
+  }
+
+  if (entry_map->second.data_type != type) {
+    return Error(R"(Expected type: "0x%02x" Actual type: "0x%02x")", type,
+                 entry_map->second.data_type);
+  }
+
+  if (entry_map->second.data_value != value) {
+    return Error(R"(Expected value: "0x%08x" Actual value: "0x%08x")", type,
+                 entry_map->second.data_value);
+  }
+
+  auto overlay_map = mapping.GetOverlayToTargetMap();
+  auto overlay_iter = overlay_map.find(entry_map->second.data_value);
+  if ((overlay_iter != overlay_map.end()) != rewrite) {
+    return Error(R"(Expected rewriting: "%s")", rewrite ? "true" : "false");
+  }
+
+  return Result<Unit>({});
+}
+
+TEST(ResourceMappingTests, ResourcesFromApkAssetsLegacy) {
+  OverlayManifestInfo info{};
+  info.target_package = "test.target";
+  info.target_name = "TestResources";
+  info.resource_mapping = 0U;  // no xml
+  auto resources = TestGetResourceMapping("/target/target.apk", "/overlay/overlay.apk", info,
+                                          PolicyFlags::POLICY_PUBLIC,
+                                          /* enforce_overlayable */ false);
+
+  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
+}
+
+TEST(ResourceMappingTests, ResourcesFromApkAssetsNonMatchingNames) {
+  OverlayManifestInfo info{};
+  info.target_package = "test.target";
+  info.target_name = "TestResources";
+  info.resource_mapping = 0x7f030003;  // xml/overlays_swap
+  auto resources = TestGetResourceMapping("/target/target.apk", "/overlay/overlay.apk", info,
+                                          PolicyFlags::POLICY_PUBLIC,
+                                          /* enforce_overlayable */ false);
+
+  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,
+                              true /* rewrite */));  // string/str1 -> string/str4
+  ASSERT_RESULT(MappingExists(res, 0x7f02000e, 0x01 /* Res_value::TYPE_REFERENCE */, 0x7f020000,
+                              true /* rewrite */));  // string/str3 -> string/str1
+  ASSERT_RESULT(MappingExists(res, 0x7f02000f, 0x01 /* Res_value::TYPE_REFERENCE */, 0x7f020001,
+                              true /* rewrite */));  // string/str4 -> string/str3
+}
+
+TEST(ResourceMappingTests, DoNotRewriteNonResourceMapping) {
+  OverlayManifestInfo info{};
+  info.target_package = "test.target";
+  info.target_name = "TestResources";
+  info.resource_mapping = 0x7f030001;  // xml/overlays_different_packages
+  auto resources = TestGetResourceMapping("/target/target.apk", "/overlay/overlay.apk", info,
+                                          PolicyFlags::POLICY_PUBLIC,
+                                          /* enforce_overlayable */ false);
+
+  ASSERT_TRUE(resources) << resources.GetErrorMessage();
+  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,
+                              false /* rewrite */));  // string/str1 -> android:string/ok
+  ASSERT_RESULT(MappingExists(res, 0x7f02000e, 0x01 /* Res_value::TYPE_REFERENCE */, 0x7f020001,
+                              true /* rewrite */));  // string/str3 -> string/str4
+}
+
+TEST(ResourceMappingTests, InlineResources) {
+  OverlayManifestInfo info{};
+  info.target_package = "test.target";
+  info.target_name = "TestResources";
+  info.resource_mapping = 0x7f030002;  // xml/overlays_inline
+  auto resources = TestGetResourceMapping("/target/target.apk", "/overlay/overlay.apk", info,
+                                          PolicyFlags::POLICY_PUBLIC,
+                                          /* enforce_overlayable */ false);
+
+  constexpr size_t overlay_string_pool_size = 8U;
+  ASSERT_TRUE(resources) << resources.GetErrorMessage();
+  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 */,
+                              overlay_string_pool_size + 0U,
+                              false /* rewrite */));  // string/str1 -> "Hello World"
+  ASSERT_RESULT(MappingExists(res, 0x7f010000, 0x10 /* Res_value::TYPE_INT_DEC */, 73U,
+                              false /* rewrite */));  // string/str1 -> "Hello World"
+}
+
+TEST(ResourceMappingTests, CreateIdmapFromApkAssetsPolicySystemPublic) {
+  auto resources =
+      TestGetResourceMapping("/target/target.apk", "/system-overlay/system-overlay.apk",
+                             PolicyFlags::POLICY_SYSTEM_PARTITION | PolicyFlags::POLICY_PUBLIC,
+                             /* enforce_overlayable */ true);
+
+  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
+}
+
+// Resources that are not declared as overlayable and resources that a protected by policies the
+// overlay does not fulfill must not map to overlay resources.
+TEST(ResourceMappingTests, CreateIdmapFromApkAssetsPolicySystemPublicInvalid) {
+  auto resources = TestGetResourceMapping(
+      "/target/target.apk", "/system-overlay-invalid/system-overlay-invalid.apk",
+      PolicyFlags::POLICY_SYSTEM_PARTITION | PolicyFlags::POLICY_PUBLIC,
+      /* enforce_overlayable */ true);
+
+  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
+}
+
+// Resources that are not declared as overlayable and resources that a protected by policies the
+// overlay does not fulfilled can map to overlay resources when overlayable enforcement is turned
+// off.
+TEST(ResourceMappingTests, ResourcesFromApkAssetsPolicySystemPublicInvalidIgnoreOverlayable) {
+  auto resources = TestGetResourceMapping(
+      "/target/target.apk", "/system-overlay-invalid/system-overlay-invalid.apk",
+      PolicyFlags::POLICY_SYSTEM_PARTITION | PolicyFlags::POLICY_PUBLIC,
+      /* enforce_overlayable */ false);
+
+  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
+}
+
+// Overlays that do not target an <overlayable> tag can overlay resources defined within any
+// <overlayable> tag.
+TEST(ResourceMappingTests, ResourcesFromApkAssetsNoDefinedOverlayableAndNoTargetName) {
+  auto resources = TestGetResourceMapping("/target/target.apk", "/overlay/overlay-no-name.apk",
+                                          PolicyFlags::POLICY_PUBLIC,
+                                          /* enforce_overlayable */ false);
+
+  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
+}
+
+// Overlays that are neither pre-installed nor signed with the same signature as the target cannot
+// overlay packages that have not defined overlayable resources.
+TEST(ResourceMappingTests, ResourcesFromApkAssetsDefaultPoliciesPublicFail) {
+  auto resources =
+      TestGetResourceMapping("/target/target-no-overlayable.apk", "/overlay/overlay-no-name.apk",
+                             PolicyFlags::POLICY_PUBLIC,
+                             /* enforce_overlayable */ true);
+
+  ASSERT_TRUE(resources) << resources.GetErrorMessage();
+  ASSERT_EQ(resources->GetTargetToOverlayMap().size(), 0U);
+}
+
+// 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(ResourceMappingTests, ResourcesFromApkAssetsDefaultPolicies) {
+  auto CheckEntries = [&](const PolicyBitmask& fulfilled_policies) -> void {
+    auto resources = TestGetResourceMapping("/target/target-no-overlayable.apk",
+                                            "/system-overlay-invalid/system-overlay-invalid.apk",
+                                            fulfilled_policies,
+                                            /* enforce_overlayable */ true);
+
+    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
+  };
+
+  CheckEntries(PolicyFlags::POLICY_SIGNATURE);
+  CheckEntries(PolicyFlags::POLICY_PRODUCT_PARTITION);
+  CheckEntries(PolicyFlags::POLICY_SYSTEM_PARTITION);
+  CheckEntries(PolicyFlags::POLICY_VENDOR_PARTITION);
+  CheckEntries(PolicyFlags::POLICY_ODM_PARTITION);
+  CheckEntries(PolicyFlags::POLICY_OEM_PARTITION);
+}
+
+}  // namespace android::idmap2
diff --git a/cmds/idmap2/tests/XmlParserTests.cpp b/cmds/idmap2/tests/XmlParserTests.cpp
new file mode 100644
index 0000000..1a7eaca
--- /dev/null
+++ b/cmds/idmap2/tests/XmlParserTests.cpp
@@ -0,0 +1,174 @@
+/*
+ * 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 <cstdio>  // fclose
+#include <memory>
+#include <string>
+
+#include "TestHelpers.h"
+#include "gmock/gmock.h"
+#include "gtest/gtest.h"
+#include "idmap2/XmlParser.h"
+#include "idmap2/ZipFile.h"
+
+namespace android::idmap2 {
+
+Result<std::unique_ptr<const XmlParser>> CreateTestParser(const std::string& test_file) {
+  auto zip = ZipFile::Open(GetTestDataPath() + "/target/target.apk");
+  if (zip == nullptr) {
+    return Error("Failed to open zip file");
+  }
+
+  auto data = zip->Uncompress(test_file);
+  if (data == nullptr) {
+    return Error("Failed to open xml file");
+  }
+
+  return XmlParser::Create(data->buf, data->size, /* copy_data */ true);
+}
+
+TEST(XmlParserTests, Create) {
+  auto xml = CreateTestParser("AndroidManifest.xml");
+  ASSERT_TRUE(xml) << xml.GetErrorMessage();
+
+  fclose(stderr);  // silence expected warnings from libandroidfw
+  const char* not_xml = "foo";
+  auto fail = XmlParser::Create(reinterpret_cast<const uint8_t*>(not_xml), strlen(not_xml));
+  ASSERT_FALSE(fail);
+}
+
+TEST(XmlParserTests, NextChild) {
+  auto xml = CreateTestParser("res/xml/test.xml");
+  ASSERT_TRUE(xml) << xml.GetErrorMessage();
+
+  auto root_iter = (*xml)->tree_iterator();
+  ASSERT_EQ(root_iter->event(), XmlParser::Event::START_TAG);
+  ASSERT_EQ(root_iter->name(), "a");
+
+  auto a_iter = root_iter.begin();
+  ASSERT_EQ(a_iter->event(), XmlParser::Event::START_TAG);
+  ASSERT_EQ(a_iter->name(), "b");
+
+  auto c_iter = a_iter.begin();
+  ASSERT_EQ(c_iter->event(), XmlParser::Event::START_TAG);
+  ASSERT_EQ(c_iter->name(), "c");
+
+  ++c_iter;
+  ASSERT_EQ(c_iter->event(), XmlParser::Event::END_TAG);
+  ASSERT_EQ(c_iter, a_iter.end());
+
+  ++a_iter;
+  ASSERT_EQ(a_iter->event(), XmlParser::Event::START_TAG);
+  ASSERT_EQ(a_iter->name(), "d");
+
+  // Skip the <e> tag.
+  ++a_iter;
+  ASSERT_EQ(a_iter->event(), XmlParser::Event::END_TAG);
+  ASSERT_EQ(a_iter, root_iter.end());
+}
+
+TEST(XmlParserTests, AttributeValues) {
+  auto xml = CreateTestParser("res/xml/test.xml");
+  ASSERT_TRUE(xml) << xml.GetErrorMessage();
+
+  // Start at the <a> tag.
+  auto root_iter = (*xml)->tree_iterator();
+
+  // Start at the <b> tag.
+  auto a_iter = root_iter.begin();
+  auto attribute_str = a_iter->GetAttributeStringValue("type_string");
+  ASSERT_TRUE(attribute_str);
+  ASSERT_EQ(*attribute_str, "fortytwo");
+
+  auto attribute_value = a_iter->GetAttributeValue("type_int_dec");
+  ASSERT_TRUE(attribute_value);
+  ASSERT_EQ(attribute_value->data, 42);
+
+  attribute_value = a_iter->GetAttributeValue("type_int_hex");
+  ASSERT_TRUE(attribute_value);
+  ASSERT_EQ(attribute_value->data, 42);
+
+  attribute_value = a_iter->GetAttributeValue("type_int_boolean");
+  ASSERT_TRUE(attribute_value);
+  ASSERT_EQ(attribute_value->data, 0xffffffff);
+}
+
+TEST(XmlParserTests, IteratorEquality) {
+  auto xml = CreateTestParser("res/xml/test.xml");
+  ASSERT_TRUE(xml) << xml.GetErrorMessage();
+
+  // Start at the <a> tag.
+  auto root_iter_1 = (*xml)->tree_iterator();
+  auto root_iter_2 = (*xml)->tree_iterator();
+  ASSERT_EQ(root_iter_1, root_iter_2);
+  ASSERT_EQ(*root_iter_1, *root_iter_2);
+
+  // Start at the <b> tag.
+  auto a_iter_1 = root_iter_1.begin();
+  auto a_iter_2 = root_iter_2.begin();
+  ASSERT_NE(a_iter_1, root_iter_1.end());
+  ASSERT_NE(a_iter_2, root_iter_2.end());
+  ASSERT_EQ(a_iter_1, a_iter_2);
+  ASSERT_EQ(*a_iter_1, *a_iter_2);
+
+  // Move to the <d> tag.
+  ++a_iter_1;
+  ++a_iter_2;
+  ASSERT_NE(a_iter_1, root_iter_1.end());
+  ASSERT_NE(a_iter_2, root_iter_2.end());
+  ASSERT_EQ(a_iter_1, a_iter_2);
+  ASSERT_EQ(*a_iter_1, *a_iter_2);
+
+  // Move to the end of the <a> tag.
+  ++a_iter_1;
+  ++a_iter_2;
+  ASSERT_EQ(a_iter_1, root_iter_1.end());
+  ASSERT_EQ(a_iter_2, root_iter_2.end());
+  ASSERT_EQ(a_iter_1, a_iter_2);
+  ASSERT_EQ(*a_iter_1, *a_iter_2);
+}
+
+TEST(XmlParserTests, Backtracking) {
+  auto xml = CreateTestParser("res/xml/test.xml");
+  ASSERT_TRUE(xml) << xml.GetErrorMessage();
+
+  // Start at the <a> tag.
+  auto root_iter_1 = (*xml)->tree_iterator();
+
+  // Start at the <b> tag.
+  auto a_iter_1 = root_iter_1.begin();
+
+  // Start a second iterator at the <a> tag.
+  auto root_iter_2 = root_iter_1;
+  ASSERT_EQ(root_iter_1, root_iter_2);
+  ASSERT_EQ(*root_iter_1, *root_iter_2);
+
+  // Move the first iterator to the end of the <a> tag.
+  auto root_iter_end_1 = root_iter_1.end();
+  ++root_iter_1;
+  ASSERT_NE(root_iter_1, root_iter_2);
+  ASSERT_NE(*root_iter_1, *root_iter_2);
+
+  // Move to the <d> tag.
+  ++a_iter_1;
+  ASSERT_NE(a_iter_1, root_iter_end_1);
+
+  // Move to the end of the <a> tag.
+  ++a_iter_1;
+  ASSERT_EQ(a_iter_1, root_iter_end_1);
+}
+
+}  // namespace android::idmap2
diff --git a/cmds/idmap2/tests/XmlTests.cpp b/cmds/idmap2/tests/XmlTests.cpp
deleted file mode 100644
index df63211..0000000
--- a/cmds/idmap2/tests/XmlTests.cpp
+++ /dev/null
@@ -1,68 +0,0 @@
-/*
- * Copyright (C) 2018 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include <cstdio>  // fclose
-
-#include "TestHelpers.h"
-#include "gmock/gmock.h"
-#include "gtest/gtest.h"
-#include "idmap2/Xml.h"
-#include "idmap2/ZipFile.h"
-
-using ::testing::IsNull;
-using ::testing::NotNull;
-
-namespace android::idmap2 {
-
-TEST(XmlTests, Create) {
-  auto zip = ZipFile::Open(GetTestDataPath() + "/target/target.apk");
-  ASSERT_THAT(zip, NotNull());
-
-  auto data = zip->Uncompress("AndroidManifest.xml");
-  ASSERT_THAT(data, NotNull());
-
-  auto xml = Xml::Create(data->buf, data->size);
-  ASSERT_THAT(xml, NotNull());
-
-  fclose(stderr);  // silence expected warnings from libandroidfw
-  const char* not_xml = "foo";
-  auto fail = Xml::Create(reinterpret_cast<const uint8_t*>(not_xml), strlen(not_xml));
-  ASSERT_THAT(fail, IsNull());
-}
-
-TEST(XmlTests, FindTag) {
-  auto zip = ZipFile::Open(GetTestDataPath() + "/target/target.apk");
-  ASSERT_THAT(zip, NotNull());
-
-  auto data = zip->Uncompress("res/xml/test.xml");
-  ASSERT_THAT(data, NotNull());
-
-  auto xml = Xml::Create(data->buf, data->size);
-  ASSERT_THAT(xml, NotNull());
-
-  auto attrs = xml->FindTag("c");
-  ASSERT_THAT(attrs, NotNull());
-  ASSERT_EQ(attrs->size(), 4U);
-  ASSERT_EQ(attrs->at("type_string"), "fortytwo");
-  ASSERT_EQ(std::stoi(attrs->at("type_int_dec")), 42);
-  ASSERT_EQ(std::stoi(attrs->at("type_int_hex")), 42);
-  ASSERT_NE(std::stoul(attrs->at("type_int_boolean")), 0U);
-
-  auto fail = xml->FindTag("does-not-exist");
-  ASSERT_THAT(fail, IsNull());
-}
-
-}  // namespace android::idmap2
diff --git a/cmds/idmap2/tests/data/overlay/AndroidManifest.xml b/cmds/idmap2/tests/data/overlay/AndroidManifest.xml
index 619bb6c..cf3691c 100644
--- a/cmds/idmap2/tests/data/overlay/AndroidManifest.xml
+++ b/cmds/idmap2/tests/data/overlay/AndroidManifest.xml
@@ -16,8 +16,11 @@
 <manifest
     xmlns:android="http://schemas.android.com/apk/res/android"
     package="test.overlay">
+
     <application android:hasCode="false"/>
+
     <overlay
         android:targetPackage="test.target"
-        android:targetName="TestResources"/>
+        android:targetName="TestResources"
+        android:resourcesMap="@xml/overlays"/>
 </manifest>
diff --git a/cmds/idmap2/tests/data/overlay/build b/cmds/idmap2/tests/data/overlay/build
index 68b9f50..b921b0d 100755
--- a/cmds/idmap2/tests/data/overlay/build
+++ b/cmds/idmap2/tests/data/overlay/build
@@ -12,7 +12,7 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
-FRAMEWORK_RES_APK=${ANDROID_BUILD_TOP}/prebuilts/sdk/current/public/android.jar
+FRAMEWORK_RES_APK=${ANDROID_PRODUCT_OUT}/system/framework/framework-res.apk
 
 aapt2 compile --dir res -o compiled.flata
 
diff --git a/cmds/idmap2/tests/data/overlay/overlay-no-name-static.apk b/cmds/idmap2/tests/data/overlay/overlay-no-name-static.apk
index 18ee43d..7c25985 100644
--- a/cmds/idmap2/tests/data/overlay/overlay-no-name-static.apk
+++ b/cmds/idmap2/tests/data/overlay/overlay-no-name-static.apk
Binary files differ
diff --git a/cmds/idmap2/tests/data/overlay/overlay-no-name.apk b/cmds/idmap2/tests/data/overlay/overlay-no-name.apk
index 6425190..c75f3e1 100644
--- a/cmds/idmap2/tests/data/overlay/overlay-no-name.apk
+++ b/cmds/idmap2/tests/data/overlay/overlay-no-name.apk
Binary files differ
diff --git a/cmds/idmap2/tests/data/overlay/overlay-static-1.apk b/cmds/idmap2/tests/data/overlay/overlay-static-1.apk
index 642ab90..5b8a6e4 100644
--- a/cmds/idmap2/tests/data/overlay/overlay-static-1.apk
+++ b/cmds/idmap2/tests/data/overlay/overlay-static-1.apk
Binary files differ
diff --git a/cmds/idmap2/tests/data/overlay/overlay-static-2.apk b/cmds/idmap2/tests/data/overlay/overlay-static-2.apk
index 2ec5602..698a1fd 100644
--- a/cmds/idmap2/tests/data/overlay/overlay-static-2.apk
+++ b/cmds/idmap2/tests/data/overlay/overlay-static-2.apk
Binary files differ
diff --git a/cmds/idmap2/tests/data/overlay/overlay.apk b/cmds/idmap2/tests/data/overlay/overlay.apk
index 5842da4..1db303f 100644
--- a/cmds/idmap2/tests/data/overlay/overlay.apk
+++ b/cmds/idmap2/tests/data/overlay/overlay.apk
Binary files differ
diff --git a/cmds/idmap2/tests/data/overlay/res/xml/overlays.xml b/cmds/idmap2/tests/data/overlay/res/xml/overlays.xml
new file mode 100644
index 0000000..edd33f7
--- /dev/null
+++ b/cmds/idmap2/tests/data/overlay/res/xml/overlays.xml
@@ -0,0 +1,23 @@
+<?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.
+-->
+<overlay>
+    <item target="string/str1" value="@string/str1"/>
+    <item target="string/str3" value="@string/str3" />
+    <item target="string/str4" value="@string/str4" />
+    <item target="integer/int1" value="@integer/int1" />
+    <item target="integer/not_in_target" value="@integer/not_in_target" />
+</overlay>
+
diff --git a/cmds/idmap2/tests/data/overlay/res/xml/overlays_different_package.xml b/cmds/idmap2/tests/data/overlay/res/xml/overlays_different_package.xml
new file mode 100644
index 0000000..aa7fefa
--- /dev/null
+++ b/cmds/idmap2/tests/data/overlay/res/xml/overlays_different_package.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.
+-->
+<overlay>
+    <item target="string/str1" value="@android:string/ok"/>
+    <item target="string/str3" value="@string/str3" />
+</overlay>
+
diff --git a/cmds/idmap2/tests/data/overlay/res/xml/overlays_inline.xml b/cmds/idmap2/tests/data/overlay/res/xml/overlays_inline.xml
new file mode 100644
index 0000000..e12b823
--- /dev/null
+++ b/cmds/idmap2/tests/data/overlay/res/xml/overlays_inline.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.
+-->
+<overlay>
+    <item target="string/str1" value="Hello World"/>
+    <item target="integer/int1" value="73" />
+</overlay>
+
diff --git a/cmds/idmap2/tests/data/overlay/res/xml/overlays_swap.xml b/cmds/idmap2/tests/data/overlay/res/xml/overlays_swap.xml
new file mode 100644
index 0000000..5728e67
--- /dev/null
+++ b/cmds/idmap2/tests/data/overlay/res/xml/overlays_swap.xml
@@ -0,0 +1,21 @@
+<?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.
+-->
+<overlay>
+    <item target="string/str1" value="@string/str4"/>
+    <item target="string/str3" value="@string/str1" />
+    <item target="string/str4" value="@string/str3" />
+    <item target="integer/int_not_in_target" value="@integer/int1" />
+</overlay>
diff --git a/cmds/idmap2/tests/data/target/res/xml/test.xml b/cmds/idmap2/tests/data/target/res/xml/test.xml
index 0fe21c6..56a3f7f 100644
--- a/cmds/idmap2/tests/data/target/res/xml/test.xml
+++ b/cmds/idmap2/tests/data/target/res/xml/test.xml
@@ -14,12 +14,15 @@
      limitations under the License.
 -->
 <a>
-    <b>
-        <c
-            type_string="fortytwo"
-            type_int_dec="42"
-            type_int_hex="0x2a"
-            type_int_boolean="true"
-            />
+    <b type_string="fortytwo"
+       type_int_dec="42"
+       type_int_hex="0x2a"
+       type_int_boolean="true">
+
+        <c />
     </b>
-</a>
+
+    <d>
+        <e />
+    </d>
+</a>
\ No newline at end of file
diff --git a/cmds/idmap2/tests/data/target/target-no-overlayable.apk b/cmds/idmap2/tests/data/target/target-no-overlayable.apk
index 033305a..2eb7c47 100644
--- a/cmds/idmap2/tests/data/target/target-no-overlayable.apk
+++ b/cmds/idmap2/tests/data/target/target-no-overlayable.apk
Binary files differ
diff --git a/cmds/idmap2/tests/data/target/target.apk b/cmds/idmap2/tests/data/target/target.apk
index 9bcd6dc..251cf46 100644
--- a/cmds/idmap2/tests/data/target/target.apk
+++ b/cmds/idmap2/tests/data/target/target.apk
Binary files differ
diff --git a/cmds/locksettings/TEST_MAPPING b/cmds/locksettings/TEST_MAPPING
index c1cba5f..56f5cc0 100644
--- a/cmds/locksettings/TEST_MAPPING
+++ b/cmds/locksettings/TEST_MAPPING
@@ -1,5 +1,5 @@
 {
-    "presubmit": [
+    "presubmit-devicepolicy": [
         {
             "name": "CtsDevicePolicyManagerTestCases",
             "options": [
diff --git a/cmds/statsd/src/StatsLogProcessor.h b/cmds/statsd/src/StatsLogProcessor.h
index f0db1b0..3d002d2 100644
--- a/cmds/statsd/src/StatsLogProcessor.h
+++ b/cmds/statsd/src/StatsLogProcessor.h
@@ -248,19 +248,6 @@
     FRIEND_TEST(ValueMetricE2eTest, TestPulledEvents_LateAlarm);
     FRIEND_TEST(ValueMetricE2eTest, TestPulledEvents_WithActivation);
 
-    FRIEND_TEST(DimensionInConditionE2eTest, TestCreateCountMetric_NoLink_OR_CombinationCondition);
-    FRIEND_TEST(DimensionInConditionE2eTest, TestCreateCountMetric_Link_OR_CombinationCondition);
-    FRIEND_TEST(DimensionInConditionE2eTest, TestDurationMetric_NoLink_OR_CombinationCondition);
-    FRIEND_TEST(DimensionInConditionE2eTest, TestDurationMetric_Link_OR_CombinationCondition);
-
-    FRIEND_TEST(DimensionInConditionE2eTest, TestDurationMetric_NoLink_SimpleCondition);
-    FRIEND_TEST(DimensionInConditionE2eTest, TestDurationMetric_Link_SimpleCondition);
-    FRIEND_TEST(DimensionInConditionE2eTest, TestDurationMetric_PartialLink_SimpleCondition);
-
-    FRIEND_TEST(DimensionInConditionE2eTest, TestDurationMetric_PartialLink_AND_CombinationCondition);
-    FRIEND_TEST(DimensionInConditionE2eTest, TestDurationMetric_NoLink_AND_CombinationCondition);
-    FRIEND_TEST(DimensionInConditionE2eTest, TestDurationMetric_Link_AND_CombinationCondition);
-
     FRIEND_TEST(AnomalyDetectionE2eTest, TestSlicedCountMetric_single_bucket);
     FRIEND_TEST(AnomalyDetectionE2eTest, TestSlicedCountMetric_multiple_buckets);
     FRIEND_TEST(AnomalyDetectionE2eTest, TestDurationMetric_SUM_single_bucket);
diff --git a/cmds/statsd/src/external/StatsPullerManager.cpp b/cmds/statsd/src/external/StatsPullerManager.cpp
index 43e33f5..5a76d1f 100644
--- a/cmds/statsd/src/external/StatsPullerManager.cpp
+++ b/cmds/statsd/src/external/StatsPullerManager.cpp
@@ -122,9 +122,10 @@
          {.puller = new StatsCompanionServicePuller(android::util::BLUETOOTH_ACTIVITY_INFO)}},
         // system_elapsed_realtime
         {android::util::SYSTEM_ELAPSED_REALTIME,
-         {.pullTimeoutNs = NS_PER_SEC / 2,
-          .coolDownNs = NS_PER_SEC,
-          .puller = new StatsCompanionServicePuller(android::util::SYSTEM_ELAPSED_REALTIME)}},
+         {.coolDownNs = NS_PER_SEC,
+          .puller = new StatsCompanionServicePuller(android::util::SYSTEM_ELAPSED_REALTIME),
+          .pullTimeoutNs = NS_PER_SEC / 2,
+         }},
         // system_uptime
         {android::util::SYSTEM_UPTIME,
          {.puller = new StatsCompanionServicePuller(android::util::SYSTEM_UPTIME)}},
diff --git a/cmds/statsd/src/main.cpp b/cmds/statsd/src/main.cpp
index 42132ee..7d446a9 100644
--- a/cmds/statsd/src/main.cpp
+++ b/cmds/statsd/src/main.cpp
@@ -53,6 +53,8 @@
     if (gStatsService != nullptr) {
         gStatsService->Terminate();
     }
+    ALOGW("statsd terminated on receiving signal %d.", sig);
+    exit(1);
 }
 
 void registerSigHandler()
diff --git a/cmds/statsd/src/metrics/CountMetricProducer.cpp b/cmds/statsd/src/metrics/CountMetricProducer.cpp
index 23d025f..b5c8e35 100644
--- a/cmds/statsd/src/metrics/CountMetricProducer.cpp
+++ b/cmds/statsd/src/metrics/CountMetricProducer.cpp
@@ -37,6 +37,7 @@
 using std::string;
 using std::unordered_map;
 using std::vector;
+using std::shared_ptr;
 
 namespace android {
 namespace os {
@@ -67,8 +68,13 @@
 CountMetricProducer::CountMetricProducer(const ConfigKey& key, const CountMetric& metric,
                                          const int conditionIndex,
                                          const sp<ConditionWizard>& wizard,
-                                         const int64_t timeBaseNs, const int64_t startTimeNs)
-    : MetricProducer(metric.id(), key, timeBaseNs, conditionIndex, 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)
+    : MetricProducer(metric.id(), key, timeBaseNs, conditionIndex, wizard, eventActivationMap,
+                     eventDeactivationMap) {
     if (metric.has_bucket()) {
         mBucketSizeNs =
                 TimeUnitToBucketSizeInMillisGuardrailed(key.GetUid(), metric.bucket()) * 1000000;
@@ -251,6 +257,7 @@
         if (newTupleCount > StatsdStats::kDimensionKeySizeHardLimit) {
             ALOGE("CountMetric %lld dropping data for dimension key %s",
                 (long long)mMetricId, newKey.toString().c_str());
+            StatsdStats::getInstance().noteHardDimensionLimitReached(mMetricId);
             return true;
         }
     }
diff --git a/cmds/statsd/src/metrics/CountMetricProducer.h b/cmds/statsd/src/metrics/CountMetricProducer.h
index b4a910c..61913c7 100644
--- a/cmds/statsd/src/metrics/CountMetricProducer.h
+++ b/cmds/statsd/src/metrics/CountMetricProducer.h
@@ -42,7 +42,11 @@
 public:
     CountMetricProducer(const ConfigKey& key, const CountMetric& countMetric,
                         const int conditionIndex, const sp<ConditionWizard>& wizard,
-                        const int64_t timeBaseNs, const int64_t startTimeNs);
+                        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 = {});
 
     virtual ~CountMetricProducer();
 
diff --git a/cmds/statsd/src/metrics/DurationMetricProducer.cpp b/cmds/statsd/src/metrics/DurationMetricProducer.cpp
index cca793b..31b90f3 100644
--- a/cmds/statsd/src/metrics/DurationMetricProducer.cpp
+++ b/cmds/statsd/src/metrics/DurationMetricProducer.cpp
@@ -36,6 +36,7 @@
 using std::string;
 using std::unordered_map;
 using std::vector;
+using std::shared_ptr;
 
 namespace android {
 namespace os {
@@ -62,14 +63,15 @@
 const int FIELD_ID_START_BUCKET_ELAPSED_MILLIS = 5;
 const int FIELD_ID_END_BUCKET_ELAPSED_MILLIS = 6;
 
-DurationMetricProducer::DurationMetricProducer(const ConfigKey& key, const DurationMetric& metric,
-                                               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)
-    : MetricProducer(metric.id(), key, timeBaseNs, conditionIndex, wizard),
+DurationMetricProducer::DurationMetricProducer(
+        const ConfigKey& key, const DurationMetric& metric, 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)
+    : MetricProducer(metric.id(), key, timeBaseNs, conditionIndex, wizard, eventActivationMap,
+                     eventDeactivationMap),
       mAggregationType(metric.aggregation_type()),
       mStartIndex(startIndex),
       mStopIndex(stopIndex),
@@ -491,6 +493,7 @@
             if (newTupleCount > StatsdStats::kDimensionKeySizeHardLimit) {
                 ALOGE("DurationMetric %lld dropping data for condition dimension key %s",
                     (long long)mMetricId, newKey.getDimensionKeyInCondition().toString().c_str());
+                StatsdStats::getInstance().noteHardDimensionLimitReached(mMetricId);
                 return true;
             }
         }
@@ -504,6 +507,7 @@
             if (newTupleCount > StatsdStats::kDimensionKeySizeHardLimit) {
                 ALOGE("DurationMetric %lld dropping data for what dimension key %s",
                     (long long)mMetricId, newKey.getDimensionKeyInWhat().toString().c_str());
+                StatsdStats::getInstance().noteHardDimensionLimitReached(mMetricId);
                 return true;
             }
         }
diff --git a/cmds/statsd/src/metrics/DurationMetricProducer.h b/cmds/statsd/src/metrics/DurationMetricProducer.h
index 56c9fd6..0592b18 100644
--- a/cmds/statsd/src/metrics/DurationMetricProducer.h
+++ b/cmds/statsd/src/metrics/DurationMetricProducer.h
@@ -42,7 +42,12 @@
                            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 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 = {});
 
     virtual ~DurationMetricProducer();
 
diff --git a/cmds/statsd/src/metrics/EventMetricProducer.cpp b/cmds/statsd/src/metrics/EventMetricProducer.cpp
index 96133bd..a60a916 100644
--- a/cmds/statsd/src/metrics/EventMetricProducer.cpp
+++ b/cmds/statsd/src/metrics/EventMetricProducer.cpp
@@ -36,6 +36,7 @@
 using std::string;
 using std::unordered_map;
 using std::vector;
+using std::shared_ptr;
 
 namespace android {
 namespace os {
@@ -54,8 +55,13 @@
 EventMetricProducer::EventMetricProducer(const ConfigKey& key, const EventMetric& metric,
                                          const int conditionIndex,
                                          const sp<ConditionWizard>& wizard,
-                                         const int64_t startTimeNs)
-    : MetricProducer(metric.id(), key, startTimeNs, conditionIndex, wizard) {
+                                         const int64_t startTimeNs,
+                                         const unordered_map<int, shared_ptr<Activation>>&
+                                                 eventActivationMap,
+                                         const unordered_map<int, vector<shared_ptr<Activation>>>&
+                                                 eventDeactivationMap)
+    : MetricProducer(metric.id(), key, startTimeNs, conditionIndex, wizard, eventActivationMap,
+                     eventDeactivationMap) {
     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 74e6bc8..aab53c8 100644
--- a/cmds/statsd/src/metrics/EventMetricProducer.h
+++ b/cmds/statsd/src/metrics/EventMetricProducer.h
@@ -35,7 +35,11 @@
 public:
     EventMetricProducer(const ConfigKey& key, const EventMetric& eventMetric,
                         const int conditionIndex, const sp<ConditionWizard>& wizard,
-                        const int64_t startTimeNs);
+                        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 = {});
 
     virtual ~EventMetricProducer();
 
diff --git a/cmds/statsd/src/metrics/GaugeMetricProducer.cpp b/cmds/statsd/src/metrics/GaugeMetricProducer.cpp
index 1f423cd..e409b6fb 100644
--- a/cmds/statsd/src/metrics/GaugeMetricProducer.cpp
+++ b/cmds/statsd/src/metrics/GaugeMetricProducer.cpp
@@ -72,8 +72,11 @@
         const sp<ConditionWizard>& wizard, 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)
-    : MetricProducer(metric.id(), key, timeBaseNs, conditionIndex, wizard),
+        const sp<StatsPullerManager>& pullerManager,
+        const unordered_map<int, shared_ptr<Activation>>& eventActivationMap,
+        const unordered_map<int, vector<shared_ptr<Activation>>>& eventDeactivationMap)
+    : MetricProducer(metric.id(), key, timeBaseNs, conditionIndex, wizard, eventActivationMap,
+            eventDeactivationMap),
       mWhatMatcherIndex(whatMatcherIndex),
       mEventMatcherWizard(matcherWizard),
       mPullerManager(pullerManager),
@@ -133,8 +136,11 @@
                                          mBucketSizeNs);
     }
 
-    // Adjust start for partial bucket
+    // Adjust start for partial first bucket and then pull if needed
     mCurrentBucketStartTimeNs = startTimeNs;
+    if (mIsActive && mIsPulled && mSamplingType == GaugeMetric::RANDOM_ONE_SAMPLE) {
+        pullAndMatchEventsLocked(mCurrentBucketStartTimeNs);
+    }
 
     VLOG("Gauge metric %lld created. bucket size %lld start_time: %lld sliced %d",
          (long long)metric.id(), (long long)mBucketSizeNs, (long long)mTimeBaseNs,
@@ -295,11 +301,6 @@
     }
 }
 
-void GaugeMetricProducer::prepareFirstBucketLocked() {
-    if (mIsActive && mIsPulled && mSamplingType == GaugeMetric::RANDOM_ONE_SAMPLE) {
-        pullAndMatchEventsLocked(mCurrentBucketStartTimeNs);
-    }
-}
 
 void GaugeMetricProducer::pullAndMatchEventsLocked(const int64_t timestampNs) {
     bool triggerPuller = false;
@@ -439,6 +440,7 @@
         if (newTupleCount > mDimensionHardLimit) {
             ALOGE("GaugeMetric %lld dropping data for dimension key %s",
                 (long long)mMetricId, newKey.toString().c_str());
+            StatsdStats::getInstance().noteHardDimensionLimitReached(mMetricId);
             return true;
         }
     }
diff --git a/cmds/statsd/src/metrics/GaugeMetricProducer.h b/cmds/statsd/src/metrics/GaugeMetricProducer.h
index a612adf..dfe1d56 100644
--- a/cmds/statsd/src/metrics/GaugeMetricProducer.h
+++ b/cmds/statsd/src/metrics/GaugeMetricProducer.h
@@ -58,11 +58,14 @@
 public:
     GaugeMetricProducer(const ConfigKey& key, const GaugeMetric& gaugeMetric,
                         const int conditionIndex, const sp<ConditionWizard>& conditionWizard,
-                        const int whatMatcherIndex,
-                        const sp<EventMatcherWizard>& matcherWizard,
+                        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 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 = {});
 
     virtual ~GaugeMetricProducer();
 
@@ -125,8 +128,6 @@
     void flushCurrentBucketLocked(const int64_t& eventTimeNs,
                                   const int64_t& nextBucketStartTimeNs) override;
 
-    void prepareFirstBucketLocked() override;
-
     void pullAndMatchEventsLocked(const int64_t timestampNs);
 
     const int mWhatMatcherIndex;
diff --git a/cmds/statsd/src/metrics/MetricProducer.cpp b/cmds/statsd/src/metrics/MetricProducer.cpp
index 1ab4fdf..3426a19 100644
--- a/cmds/statsd/src/metrics/MetricProducer.cpp
+++ b/cmds/statsd/src/metrics/MetricProducer.cpp
@@ -40,6 +40,29 @@
 const int FIELD_ID_ACTIVE_EVENT_ACTIVATION_REMAINING_TTL_NANOS = 2;
 const int FIELD_ID_ACTIVE_EVENT_ACTIVATION_STATE = 3;
 
+MetricProducer::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)
+        : 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()) {
+    }
+
 void MetricProducer::onMatchedLogEventLocked(const size_t matcherIndex, const LogEvent& event) {
     if (!mIsActive) {
         return;
@@ -97,24 +120,6 @@
     }
 }
 
-void MetricProducer::addActivation(int activationTrackerIndex, const ActivationType& activationType,
-        int64_t ttl_seconds, int deactivationTrackerIndex) {
-    std::lock_guard<std::mutex> lock(mMutex);
-    // When a metric producer does not depend on any activation, its mIsActive is true.
-    // Therefore, if this is the 1st activation, mIsActive will turn to false. Otherwise it does not
-    // change.
-    if  (mEventActivationMap.empty()) {
-        mIsActive = false;
-    }
-    std::shared_ptr<Activation> activation =
-            std::make_shared<Activation>(activationType, ttl_seconds * NS_PER_SEC);
-    mEventActivationMap.emplace(activationTrackerIndex, activation);
-    if (-1 != deactivationTrackerIndex) {
-        auto& deactivationList = mEventDeactivationMap[deactivationTrackerIndex];
-        deactivationList.push_back(activation);
-    }
-}
-
 void MetricProducer::activateLocked(int activationTrackerIndex, int64_t elapsedTimestampNs) {
     auto it = mEventActivationMap.find(activationTrackerIndex);
     if (it == mEventActivationMap.end()) {
diff --git a/cmds/statsd/src/metrics/MetricProducer.h b/cmds/statsd/src/metrics/MetricProducer.h
index fdbdc83..1e1eb69 100644
--- a/cmds/statsd/src/metrics/MetricProducer.h
+++ b/cmds/statsd/src/metrics/MetricProducer.h
@@ -69,6 +69,19 @@
     NO_TIME_CONSTRAINTS = 2
 };
 
+struct Activation {
+    Activation(const ActivationType& activationType, const int64_t ttlNs)
+        : ttl_ns(ttlNs),
+          start_ns(0),
+          state(ActivationState::kNotActive),
+          activationType(activationType) {}
+
+    const int64_t ttl_ns;
+    int64_t start_ns;
+    ActivationState state;
+    const ActivationType activationType;
+};
+
 // A MetricProducer is responsible for compute one single metrics, creating stats log report, and
 // 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
@@ -76,21 +89,10 @@
 class MetricProducer : public virtual PackageInfoListener {
 public:
     MetricProducer(const int64_t& metricId, const ConfigKey& key, const int64_t timeBaseNs,
-                   const int conditionIndex, const sp<ConditionWizard>& wizard)
-        : 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),
-          mIsActive(true) {
-    }
+                   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);
 
     virtual ~MetricProducer(){};
 
@@ -188,11 +190,6 @@
         dropDataLocked(dropTimeNs);
     }
 
-    void prepareFirstBucket() {
-        std::lock_guard<std::mutex> lock(mMutex);
-        prepareFirstBucketLocked();
-    }
-
     void loadActiveMetric(const ActiveMetric& activeMetric, int64_t currentTimeNs) {
         std::lock_guard<std::mutex> lock(mMutex);
         loadActiveMetricLocked(activeMetric, currentTimeNs);
@@ -215,9 +212,6 @@
 
     void flushIfExpire(int64_t elapsedTimestampNs);
 
-    void addActivation(int activationTrackerIndex, const ActivationType& activationType,
-            int64_t ttl_seconds, int deactivationTrackerIndex = -1);
-
     void writeActiveMetricToProtoOutputStream(
             int64_t currentTimeNs, const DumpReportReason reason, ProtoOutputStream* proto);
 
@@ -310,7 +304,6 @@
     virtual size_t byteSizeLocked() const = 0;
     virtual void dumpStatesLocked(FILE* out, bool verbose) const = 0;
     virtual void dropDataLocked(const int64_t dropTimeNs) = 0;
-    virtual void prepareFirstBucketLocked() {};
     void loadActiveMetricLocked(const ActiveMetric& activeMetric, int64_t currentTimeNs);
     void activateLocked(int activationTrackerIndex, int64_t elapsedTimestampNs);
     void cancelEventActivationLocked(int deactivationTrackerIndex);
@@ -379,19 +372,6 @@
 
     mutable std::mutex mMutex;
 
-    struct Activation {
-        Activation(const ActivationType& activationType, const int64_t ttlNs)
-            : ttl_ns(ttlNs),
-              start_ns(0),
-              state(ActivationState::kNotActive),
-              activationType(activationType) {}
-
-        const int64_t ttl_ns;
-        int64_t start_ns;
-        ActivationState state;
-        const ActivationType activationType;
-    };
-
     // When the metric producer has multiple activations, these activations are ORed to determine
     // whether the metric producer is ready to generate metrics.
     std::unordered_map<int, std::shared_ptr<Activation>> mEventActivationMap;
diff --git a/cmds/statsd/src/metrics/ValueMetricProducer.cpp b/cmds/statsd/src/metrics/ValueMetricProducer.cpp
index bc16024..7fe5a83 100644
--- a/cmds/statsd/src/metrics/ValueMetricProducer.cpp
+++ b/cmds/statsd/src/metrics/ValueMetricProducer.cpp
@@ -81,8 +81,11 @@
         const ConfigKey& key, const ValueMetric& metric, 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)
-    : MetricProducer(metric.id(), key, timeBaseNs, conditionIndex, conditionWizard),
+        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)
+    : MetricProducer(metric.id(), key, timeBaseNs, conditionIndex, conditionWizard,
+                     eventActivationMap, eventDeactivationMap),
       mWhatMatcherIndex(whatMatcherIndex),
       mEventMatcherWizard(matcherWizard),
       mPullerManager(pullerManager),
@@ -108,7 +111,7 @@
       mMaxPullDelayNs(metric.max_pull_delay_sec() > 0 ? metric.max_pull_delay_sec() * NS_PER_SEC
                                                       : StatsdStats::kPullMaxDelayNs),
       mSplitBucketForAppUpgrade(metric.split_bucket_for_app_upgrade()),
-      // Condition timer will be set in prepareFirstBucketLocked.
+      // Condition timer will be set later within the constructor after pulling events
       mConditionTimer(false, timeBaseNs) {
     int64_t bucketSizeMills = 0;
     if (metric.has_bucket()) {
@@ -154,6 +157,15 @@
     // Adjust start for partial bucket
     mCurrentBucketStartTimeNs = startTimeNs;
     mConditionTimer.newBucketStart(mCurrentBucketStartTimeNs);
+
+     // Kicks off the puller immediately if condition is true and diff based.
+    if (mIsActive && mIsPulled && mCondition == ConditionState::kTrue && mUseDiff) {
+        pullAndMatchEventsLocked(mCurrentBucketStartTimeNs, mCondition);
+    }
+    // Now that activations are processed, start the condition timer if needed.
+    mConditionTimer.onConditionChanged(mIsActive && mCondition == ConditionState::kTrue,
+                                       mCurrentBucketStartTimeNs);
+
     VLOG("value metric %lld created. bucket size %lld start_time: %lld", (long long)metric.id(),
          (long long)mBucketSizeNs, (long long)mTimeBaseNs);
 }
@@ -165,16 +177,6 @@
     }
 }
 
-void ValueMetricProducer::prepareFirstBucketLocked() {
-    // Kicks off the puller immediately if condition is true and diff based.
-    if (mIsActive && mIsPulled && mCondition == ConditionState::kTrue && mUseDiff) {
-        pullAndMatchEventsLocked(mCurrentBucketStartTimeNs, mCondition);
-    }
-    // Now that activations are processed, start the condition timer if needed.
-    mConditionTimer.onConditionChanged(mIsActive && mCondition == ConditionState::kTrue,
-                                       mCurrentBucketStartTimeNs);
-}
-
 void ValueMetricProducer::onSlicedConditionMayChangeLocked(bool overallCondition,
                                                            const int64_t eventTime) {
     VLOG("Metric %lld onSlicedConditionMayChange", (long long)mMetricId);
diff --git a/cmds/statsd/src/metrics/ValueMetricProducer.h b/cmds/statsd/src/metrics/ValueMetricProducer.h
index 739f6ef..d7cd397 100644
--- a/cmds/statsd/src/metrics/ValueMetricProducer.h
+++ b/cmds/statsd/src/metrics/ValueMetricProducer.h
@@ -54,10 +54,13 @@
 public:
     ValueMetricProducer(const ConfigKey& key, const ValueMetric& valueMetric,
                         const int conditionIndex, const sp<ConditionWizard>& conditionWizard,
-                        const int whatMatcherIndex,
-                        const sp<EventMatcherWizard>& matcherWizard,
+                        const int whatMatcherIndex, const sp<EventMatcherWizard>& matcherWizard,
                         const int pullTagId, const int64_t timeBaseNs, const int64_t startTimeNs,
-                        const sp<StatsPullerManager>& pullerManager);
+                        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 = {});
 
     virtual ~ValueMetricProducer();
 
@@ -116,8 +119,6 @@
     void flushCurrentBucketLocked(const int64_t& eventTimeNs,
                                   const int64_t& nextBucketStartTimeNs) override;
 
-    void prepareFirstBucketLocked() override;
-
     void dropDataLocked(const int64_t dropTimeNs) override;
 
     // Calculate previous bucket end time based on current time.
diff --git a/cmds/statsd/src/metrics/metrics_manager_util.cpp b/cmds/statsd/src/metrics/metrics_manager_util.cpp
index 40484f4..0fee71e 100644
--- a/cmds/statsd/src/metrics/metrics_manager_util.cpp
+++ b/cmds/statsd/src/metrics/metrics_manager_util.cpp
@@ -18,6 +18,7 @@
 #include "Log.h"
 
 #include "metrics_manager_util.h"
+#include "MetricProducer.h"
 
 #include "../condition/CombinationConditionTracker.h"
 #include "../condition/SimpleConditionTracker.h"
@@ -137,6 +138,62 @@
     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.
+// Returns false if there are errors.
+bool handleMetricActivation(
+        const StatsdConfig& config,
+        const int64_t metricId,
+        const int metricIndex,
+        const unordered_map<int64_t, int>& metricToActivationMap,
+        const unordered_map<int64_t, int>& logTrackerMap,
+        unordered_map<int, vector<int>>& activationAtomTrackerToMetricMap,
+        unordered_map<int, vector<int>>& deactivationAtomTrackerToMetricMap,
+        vector<int>& metricsWithActivation,
+        unordered_map<int, shared_ptr<Activation>>& eventActivationMap,
+        unordered_map<int, vector<shared_ptr<Activation>>>& eventDeactivationMap) {
+    // Check if metric has an associated activation
+    auto itr = metricToActivationMap.find(metricId);
+    if (itr == metricToActivationMap.end()) return true;
+
+    int activationIndex = itr->second;
+    const MetricActivation& metricActivation = config.metric_activation(activationIndex);
+
+    for (int i = 0; i < metricActivation.event_activation_size(); i++) {
+        const EventActivation& activation = metricActivation.event_activation(i);
+
+        auto itr = logTrackerMap.find(activation.atom_matcher_id());
+        if (itr == logTrackerMap.end()) {
+            ALOGE("Atom matcher not found for event activation.");
+            return false;
+        }
+
+        ActivationType activationType = (activation.has_activation_type()) ?
+                activation.activation_type() : metricActivation.activation_type();
+        std::shared_ptr<Activation> activationWrapper = std::make_shared<Activation>(
+                activationType, activation.ttl_seconds() * NS_PER_SEC);
+
+        int atomMatcherIndex = itr->second;
+        activationAtomTrackerToMetricMap[atomMatcherIndex].push_back(metricIndex);
+        eventActivationMap.emplace(atomMatcherIndex, activationWrapper);
+
+        if (activation.has_deactivation_atom_matcher_id()) {
+            itr = logTrackerMap.find(activation.deactivation_atom_matcher_id());
+            if (itr == logTrackerMap.end()) {
+                ALOGE("Atom matcher not found for event deactivation.");
+                return false;
+            }
+            int deactivationAtomMatcherIndex = itr->second;
+            deactivationAtomTrackerToMetricMap[deactivationAtomMatcherIndex].push_back(metricIndex);
+            eventDeactivationMap[deactivationAtomMatcherIndex].push_back(activationWrapper);
+        }
+    }
+
+    metricsWithActivation.push_back(metricIndex);
+    return true;
+}
+
 bool initLogTrackers(const StatsdConfig& config, const UidMap& uidMap,
                      unordered_map<int64_t, int>& logTrackerMap,
                      vector<sp<LogMatchingTracker>>& allAtomMatchers, set<int>& allTagIds) {
@@ -293,16 +350,33 @@
                  const vector<sp<LogMatchingTracker>>& allAtomMatchers,
                  vector<sp<ConditionTracker>>& allConditionTrackers,
                  vector<sp<MetricProducer>>& allMetricProducers,
-                 unordered_map<int, std::vector<int>>& conditionToMetricMap,
-                 unordered_map<int, std::vector<int>>& trackerToMetricMap,
-                 unordered_map<int64_t, int>& metricMap, std::set<int64_t>& noReportMetricIds) {
+                 unordered_map<int, vector<int>>& conditionToMetricMap,
+                 unordered_map<int, vector<int>>& trackerToMetricMap,
+                 unordered_map<int64_t, int>& metricMap, std::set<int64_t>& noReportMetricIds,
+                 unordered_map<int, vector<int>>& activationAtomTrackerToMetricMap,
+                 unordered_map<int, vector<int>>& deactivationAtomTrackerToMetricMap,
+                 vector<int>& metricsWithActivation) {
     sp<ConditionWizard> wizard = new ConditionWizard(allConditionTrackers);
     sp<EventMatcherWizard> matcherWizard = new EventMatcherWizard(allAtomMatchers);
     const int allMetricsCount = config.count_metric_size() + config.duration_metric_size() +
-                                config.event_metric_size() + config.value_metric_size();
+                                config.event_metric_size() + config.gauge_metric_size() +
+                                config.value_metric_size();
     allMetricProducers.reserve(allMetricsCount);
     StatsPullerManager statsPullerManager;
 
+    // Construct map from metric id to metric activation index. The map will be used to determine
+    // the metric activation corresponding to a metric.
+    unordered_map<int64_t, int> metricToActivationMap;
+    for (int i = 0; i < config.metric_activation_size(); i++) {
+        const MetricActivation& metricActivation = config.metric_activation(i);
+        int64_t metricId = metricActivation.metric_id();
+        if (metricToActivationMap.find(metricId) != metricToActivationMap.end()) {
+            ALOGE("Metric %lld has multiple MetricActivations", (long long) metricId);
+            return false;
+        }
+        metricToActivationMap.insert({metricId, i});
+    }
+
     // Build MetricProducers for each metric defined in config.
     // build CountMetricProducer
     for (int i = 0; i < config.count_metric_size(); i++) {
@@ -337,8 +411,17 @@
             }
         }
 
-        sp<MetricProducer> countProducer =
-                new CountMetricProducer(key, metric, conditionIndex, wizard, timeBaseTimeNs, currentTimeNs);
+        unordered_map<int, shared_ptr<Activation>> eventActivationMap;
+        unordered_map<int, vector<shared_ptr<Activation>>> eventDeactivationMap;
+        bool success = handleMetricActivation(config, metric.id(), metricIndex,
+                metricToActivationMap, logTrackerMap, activationAtomTrackerToMetricMap,
+                deactivationAtomTrackerToMetricMap, metricsWithActivation, eventActivationMap,
+                eventDeactivationMap);
+        if (!success) return false;
+
+        sp<MetricProducer> countProducer = new CountMetricProducer(
+                key, metric, conditionIndex, wizard, timeBaseTimeNs, currentTimeNs,
+                eventActivationMap, eventDeactivationMap);
         allMetricProducers.push_back(countProducer);
     }
 
@@ -406,9 +489,18 @@
             }
         }
 
+        unordered_map<int, shared_ptr<Activation>> eventActivationMap;
+        unordered_map<int, vector<shared_ptr<Activation>>> eventDeactivationMap;
+        bool success = handleMetricActivation(config, metric.id(), metricIndex,
+                metricToActivationMap, logTrackerMap, activationAtomTrackerToMetricMap,
+                deactivationAtomTrackerToMetricMap, metricsWithActivation, eventActivationMap,
+                eventDeactivationMap);
+        if (!success) return false;
+
         sp<MetricProducer> durationMetric = new DurationMetricProducer(
                 key, metric, conditionIndex, trackerIndices[0], trackerIndices[1],
-                trackerIndices[2], nesting, wizard, internalDimensions, timeBaseTimeNs, currentTimeNs);
+                trackerIndices[2], nesting, wizard, internalDimensions, timeBaseTimeNs,
+                currentTimeNs, eventActivationMap, eventDeactivationMap);
 
         allMetricProducers.push_back(durationMetric);
     }
@@ -443,8 +535,17 @@
             }
         }
 
-        sp<MetricProducer> eventMetric =
-                new EventMetricProducer(key, metric, conditionIndex, wizard, timeBaseTimeNs);
+        unordered_map<int, shared_ptr<Activation>> eventActivationMap;
+        unordered_map<int, vector<shared_ptr<Activation>>> eventDeactivationMap;
+        bool success = handleMetricActivation(config, metric.id(), metricIndex,
+                metricToActivationMap, logTrackerMap, activationAtomTrackerToMetricMap,
+                deactivationAtomTrackerToMetricMap, metricsWithActivation, eventActivationMap,
+                eventDeactivationMap);
+        if (!success) return false;
+
+        sp<MetricProducer> eventMetric = new EventMetricProducer(
+                key, metric, conditionIndex, wizard, timeBaseTimeNs, eventActivationMap,
+                eventDeactivationMap);
 
         allMetricProducers.push_back(eventMetric);
     }
@@ -500,9 +601,18 @@
             }
         }
 
+        unordered_map<int, shared_ptr<Activation>> eventActivationMap;
+        unordered_map<int, vector<shared_ptr<Activation>>> eventDeactivationMap;
+        bool success = handleMetricActivation(config, metric.id(), metricIndex,
+                metricToActivationMap, logTrackerMap, activationAtomTrackerToMetricMap,
+                deactivationAtomTrackerToMetricMap, metricsWithActivation, eventActivationMap,
+                eventDeactivationMap);
+        if (!success) return false;
+
         sp<MetricProducer> valueProducer = new ValueMetricProducer(
                 key, metric, conditionIndex, wizard, trackerIndex, matcherWizard, pullTagId,
-                timeBaseTimeNs, currentTimeNs, pullerManager);
+                timeBaseTimeNs, currentTimeNs, pullerManager, eventActivationMap,
+                eventDeactivationMap);
         allMetricProducers.push_back(valueProducer);
     }
 
@@ -586,10 +696,19 @@
             }
         }
 
+        unordered_map<int, shared_ptr<Activation>> eventActivationMap;
+        unordered_map<int, vector<shared_ptr<Activation>>> eventDeactivationMap;
+        bool success = handleMetricActivation(config, metric.id(), metricIndex,
+                metricToActivationMap, logTrackerMap, activationAtomTrackerToMetricMap,
+                deactivationAtomTrackerToMetricMap, metricsWithActivation, eventActivationMap,
+                eventDeactivationMap);
+        if (!success) return false;
+
         sp<MetricProducer> gaugeProducer = new GaugeMetricProducer(
                 key, metric, conditionIndex, wizard,
                 trackerIndex, matcherWizard, pullTagId, triggerAtomId, atomTagId,
-                timeBaseTimeNs, currentTimeNs, pullerManager);
+                timeBaseTimeNs, currentTimeNs, pullerManager,
+                eventActivationMap, eventDeactivationMap);
         allMetricProducers.push_back(gaugeProducer);
     }
     for (int i = 0; i < config.no_report_metric_size(); ++i) {
@@ -707,73 +826,6 @@
     return true;
 }
 
-bool initMetricActivations(const ConfigKey& key, const StatsdConfig& config,
-                           const int64_t currentTimeNs,
-                           const unordered_map<int64_t, int> &logEventTrackerMap,
-                           const unordered_map<int64_t, int> &metricProducerMap,
-                           vector<sp<MetricProducer>>& allMetricProducers,
-                           unordered_map<int, std::vector<int>>& activationAtomTrackerToMetricMap,
-                           unordered_map<int, std::vector<int>>& deactivationAtomTrackerToMetricMap,
-                           vector<int>& metricsWithActivation) {
-    for (int i = 0; i < config.metric_activation_size(); ++i) {
-        const MetricActivation& metric_activation = config.metric_activation(i);
-        auto itr = metricProducerMap.find(metric_activation.metric_id());
-        if (itr == metricProducerMap.end()) {
-            ALOGE("Metric id not found in metric activation: %lld",
-                (long long)metric_activation.metric_id());
-            return false;
-        }
-        const int metricTrackerIndex = itr->second;
-        if (metricTrackerIndex < 0 || metricTrackerIndex >= (int)allMetricProducers.size()) {
-            ALOGE("Invalid metric tracker index.");
-            return false;
-        }
-        const sp<MetricProducer>& metric = allMetricProducers[metricTrackerIndex];
-        metricsWithActivation.push_back(metricTrackerIndex);
-        for (int j = 0; j < metric_activation.event_activation_size(); ++j) {
-            const EventActivation& activation = metric_activation.event_activation(j);
-            auto logTrackerIt = logEventTrackerMap.find(activation.atom_matcher_id());
-            if (logTrackerIt == logEventTrackerMap.end()) {
-                ALOGE("Atom matcher not found for event activation.");
-                return false;
-            }
-            const int atomMatcherIndex = logTrackerIt->second;
-            activationAtomTrackerToMetricMap[atomMatcherIndex].push_back(
-                metricTrackerIndex);
-
-            ActivationType activationType;
-            if (activation.has_activation_type()) {
-                activationType = activation.activation_type();
-            } else {
-                activationType = metric_activation.activation_type();
-            }
-
-            if (activation.has_deactivation_atom_matcher_id()) {
-                auto deactivationAtomMatcherIt =
-                        logEventTrackerMap.find(activation.deactivation_atom_matcher_id());
-                if (deactivationAtomMatcherIt == logEventTrackerMap.end()) {
-                    ALOGE("Atom matcher not found for event deactivation.");
-                    return false;
-                }
-                const int deactivationMatcherIndex = deactivationAtomMatcherIt->second;
-                deactivationAtomTrackerToMetricMap[deactivationMatcherIndex]
-                        .push_back(metricTrackerIndex);
-                metric->addActivation(atomMatcherIndex, activationType, activation.ttl_seconds(),
-                                      deactivationMatcherIndex);
-            } else {
-                metric->addActivation(atomMatcherIndex, activationType, activation.ttl_seconds());
-            }
-        }
-    }
-    return true;
-}
-
-void prepareFirstBucket(const vector<sp<MetricProducer>>& allMetricProducers) {
-    for (const auto& metric: allMetricProducers) {
-        metric->prepareFirstBucket();
-    }
-}
-
 bool initStatsdConfig(const ConfigKey& key, const StatsdConfig& config, UidMap& uidMap,
                       const sp<StatsPullerManager>& pullerManager,
                       const sp<AlarmMonitor>& anomalyAlarmMonitor,
@@ -810,7 +862,8 @@
     if (!initMetrics(key, config, timeBaseNs, currentTimeNs, uidMap, pullerManager, logTrackerMap,
                      conditionTrackerMap, allAtomMatchers, allConditionTrackers, allMetricProducers,
                      conditionToMetricMap, trackerToMetricMap, metricProducerMap,
-                     noReportMetricIds)) {
+                     noReportMetricIds, activationAtomTrackerToMetricMap,
+                     deactivationAtomTrackerToMetricMap, metricsWithActivation)) {
         ALOGE("initMetricProducers failed");
         return false;
     }
@@ -824,14 +877,6 @@
         ALOGE("initAlarms failed");
         return false;
     }
-    if (!initMetricActivations(key, config, currentTimeNs, logTrackerMap, metricProducerMap,
-            allMetricProducers, activationAtomTrackerToMetricMap,
-            deactivationAtomTrackerToMetricMap, metricsWithActivation)) {
-        ALOGE("initMetricActivations failed");
-        return false;
-    }
-
-    prepareFirstBucket(allMetricProducers);
 
     return true;
 }
diff --git a/cmds/statsd/src/metrics/metrics_manager_util.h b/cmds/statsd/src/metrics/metrics_manager_util.h
index 3704969..3802948 100644
--- a/cmds/statsd/src/metrics/metrics_manager_util.h
+++ b/cmds/statsd/src/metrics/metrics_manager_util.h
@@ -91,7 +91,10 @@
         std::vector<sp<MetricProducer>>& allMetricProducers,
         std::unordered_map<int, std::vector<int>>& conditionToMetricMap,
         std::unordered_map<int, std::vector<int>>& trackerToMetricMap,
-        std::set<int64_t>& noReportMetricIds);
+        std::set<int64_t>& noReportMetricIds,
+        std::unordered_map<int, std::vector<int>>& activationAtomTrackerToMetricMap,
+        std::unordered_map<int, std::vector<int>>& deactivationAtomTrackerToMetricMap,
+        std::vector<int>& metricsWithActivation);
 
 // Initialize MetricsManager from StatsdConfig.
 // Parameters are the members of MetricsManager. See MetricsManager for declaration.
diff --git a/cmds/statsd/tests/StatsLogProcessor_test.cpp b/cmds/statsd/tests/StatsLogProcessor_test.cpp
index 76ee9a6..460b9e0 100644
--- a/cmds/statsd/tests/StatsLogProcessor_test.cpp
+++ b/cmds/statsd/tests/StatsLogProcessor_test.cpp
@@ -1199,87 +1199,66 @@
 
     ConfigKey cfgKey1(uid, 12341);
     long timeBase1 = 1;
-    sp<StatsLogProcessor> processor =
+    sp<StatsLogProcessor> processor1 =
             CreateStatsLogProcessor(timeBase1, timeBase1, config1, cfgKey1);
 
     // Metric 1 is not active.
     // Metric 2 is active.
     // {{{---------------------------------------------------------------------------
-    EXPECT_EQ(1, processor->mMetricsManagers.size());
-    auto it = processor->mMetricsManagers.find(cfgKey1);
-    EXPECT_TRUE(it != processor->mMetricsManagers.end());
+    EXPECT_EQ(1, processor1->mMetricsManagers.size());
+    auto it = processor1->mMetricsManagers.find(cfgKey1);
+    EXPECT_TRUE(it != processor1->mMetricsManagers.end());
     auto& metricsManager1 = it->second;
     EXPECT_TRUE(metricsManager1->isActive());
 
-    auto metricIt = metricsManager1->mAllMetricProducers.begin();
-    for (; metricIt != metricsManager1->mAllMetricProducers.end(); metricIt++) {
-        if ((*metricIt)->getMetricId() == metricId1) {
-            break;
-        }
-    }
-    EXPECT_TRUE(metricIt != metricsManager1->mAllMetricProducers.end());
-    auto& metricProducer1 = *metricIt;
-    EXPECT_FALSE(metricProducer1->isActive());
+    EXPECT_EQ(metricsManager1->mAllMetricProducers.size(), 2);
+    // We assume that the index of a MetricProducer within the mAllMetricProducers
+    // array follows the order in which metrics are added to the config.
+    auto& metricProducer1_1 = metricsManager1->mAllMetricProducers[0];
+    EXPECT_EQ(metricProducer1_1->getMetricId(), metricId1);
+    EXPECT_FALSE(metricProducer1_1->isActive());  // inactive due to associated MetricActivation
 
-    metricIt = metricsManager1->mAllMetricProducers.begin();
-    for (; metricIt != metricsManager1->mAllMetricProducers.end(); metricIt++) {
-        if ((*metricIt)->getMetricId() == metricId2) {
-            break;
-        }
-    }
-    EXPECT_TRUE(metricIt != metricsManager1->mAllMetricProducers.end());
-    auto& metricProducer2 = *metricIt;
-    EXPECT_TRUE(metricProducer2->isActive());
+    auto& metricProducer1_2 = metricsManager1->mAllMetricProducers[1];
+    EXPECT_EQ(metricProducer1_2->getMetricId(), metricId2);
+    EXPECT_TRUE(metricProducer1_2->isActive());
 
-    int i = 0;
-    for (; i < metricsManager1->mAllAtomMatchers.size(); i++) {
-        if (metricsManager1->mAllAtomMatchers[i]->getId() ==
-                metric1ActivationTrigger1->atom_matcher_id()) {
-            break;
-        }
-    }
-    const auto& activation1 = metricProducer1->mEventActivationMap.at(i);
-    EXPECT_EQ(100 * NS_PER_SEC, activation1->ttl_ns);
-    EXPECT_EQ(0, activation1->start_ns);
-    EXPECT_EQ(kNotActive, activation1->state);
-    EXPECT_EQ(ACTIVATE_ON_BOOT, activation1->activationType);
+    EXPECT_EQ(metricProducer1_1->mEventActivationMap.size(), 2);
+    // The key in mEventActivationMap is the index of the associated atom matcher. We assume
+    // that matchers are indexed in the order that they are added to the config.
+    const auto& activation1_1_1 = metricProducer1_1->mEventActivationMap.at(0);
+    EXPECT_EQ(100 * NS_PER_SEC, activation1_1_1->ttl_ns);
+    EXPECT_EQ(0, activation1_1_1->start_ns);
+    EXPECT_EQ(kNotActive, activation1_1_1->state);
+    EXPECT_EQ(ACTIVATE_ON_BOOT, activation1_1_1->activationType);
 
-    i = 0;
-    for (; i < metricsManager1->mAllAtomMatchers.size(); i++) {
-        if (metricsManager1->mAllAtomMatchers[i]->getId() ==
-                metric1ActivationTrigger2->atom_matcher_id()) {
-            break;
-        }
-    }
-    const auto& activation2 = metricProducer1->mEventActivationMap.at(i);
-    EXPECT_EQ(200 * NS_PER_SEC, activation2->ttl_ns);
-    EXPECT_EQ(0, activation2->start_ns);
-    EXPECT_EQ(kNotActive, activation2->state);
-    EXPECT_EQ(ACTIVATE_IMMEDIATELY, activation2->activationType);
+    const auto& activation1_1_2 = metricProducer1_1->mEventActivationMap.at(1);
+    EXPECT_EQ(200 * NS_PER_SEC, activation1_1_2->ttl_ns);
+    EXPECT_EQ(0, activation1_1_2->start_ns);
+    EXPECT_EQ(kNotActive, activation1_1_2->state);
+    EXPECT_EQ(ACTIVATE_IMMEDIATELY, activation1_1_2->activationType);
     // }}}------------------------------------------------------------------------------
 
     // Trigger Activation 1 for Metric 1
     std::vector<AttributionNodeInternal> attributions1 = {CreateAttribution(111, "App1")};
     auto event = CreateAcquireWakelockEvent(attributions1, "wl1", 100 + timeBase1);
-    processor->OnLogEvent(event.get());
+    processor1->OnLogEvent(event.get());
 
     // Metric 1 is not active; Activation 1 set to kActiveOnBoot
     // Metric 2 is active.
     // {{{---------------------------------------------------------------------------
-    EXPECT_FALSE(metricProducer1->isActive());
-    EXPECT_EQ(0, activation1->start_ns);
-    EXPECT_EQ(kActiveOnBoot, activation1->state);
-    EXPECT_EQ(0, activation2->start_ns);
-    EXPECT_EQ(kNotActive, activation2->state);
+    EXPECT_FALSE(metricProducer1_1->isActive());
+    EXPECT_EQ(0, activation1_1_1->start_ns);
+    EXPECT_EQ(kActiveOnBoot, activation1_1_1->state);
+    EXPECT_EQ(0, activation1_1_2->start_ns);
+    EXPECT_EQ(kNotActive, activation1_1_2->state);
 
-    EXPECT_TRUE(metricProducer2->isActive());
+    EXPECT_TRUE(metricProducer1_2->isActive());
     // }}}-----------------------------------------------------------------------------
 
     // Simulate shutdown by saving state to disk
     int64_t shutDownTime = timeBase1 + 100 * NS_PER_SEC;
-    processor->SaveActiveConfigsToDisk(shutDownTime);
-    EXPECT_FALSE(metricProducer1->isActive());
-    int64_t ttl1 = metric1ActivationTrigger1->ttl_seconds() * NS_PER_SEC;
+    processor1->SaveActiveConfigsToDisk(shutDownTime);
+    EXPECT_FALSE(metricProducer1_1->isActive());
 
     // Simulate device restarted state by creating new instance of StatsLogProcessor with the
     // same config.
@@ -1293,55 +1272,34 @@
     EXPECT_EQ(1, processor2->mMetricsManagers.size());
     it = processor2->mMetricsManagers.find(cfgKey1);
     EXPECT_TRUE(it != processor2->mMetricsManagers.end());
-    auto& metricsManager1001 = it->second;
-    EXPECT_TRUE(metricsManager1001->isActive());
+    auto& metricsManager2 = it->second;
+    EXPECT_TRUE(metricsManager2->isActive());
 
-    metricIt = metricsManager1001->mAllMetricProducers.begin();
-    for (; metricIt != metricsManager1001->mAllMetricProducers.end(); metricIt++) {
-        if ((*metricIt)->getMetricId() == metricId1) {
-            break;
-        }
-    }
-    EXPECT_TRUE(metricIt != metricsManager1001->mAllMetricProducers.end());
-    auto& metricProducer1001 = *metricIt;
-    EXPECT_FALSE(metricProducer1001->isActive());
+    EXPECT_EQ(metricsManager2->mAllMetricProducers.size(), 2);
+    // We assume that the index of a MetricProducer within the mAllMetricProducers
+    // array follows the order in which metrics are added to the config.
+    auto& metricProducer2_1 = metricsManager2->mAllMetricProducers[0];
+    EXPECT_EQ(metricProducer2_1->getMetricId(), metricId1);
+    EXPECT_FALSE(metricProducer2_1->isActive());
 
-    metricIt = metricsManager1001->mAllMetricProducers.begin();
-    for (; metricIt != metricsManager1001->mAllMetricProducers.end(); metricIt++) {
-        if ((*metricIt)->getMetricId() == metricId2) {
-            break;
-        }
-    }
-    EXPECT_TRUE(metricIt != metricsManager1001->mAllMetricProducers.end());
-    auto& metricProducer1002 = *metricIt;
-    EXPECT_TRUE(metricProducer1002->isActive());
+    auto& metricProducer2_2 = metricsManager2->mAllMetricProducers[1];
+    EXPECT_EQ(metricProducer2_2->getMetricId(), metricId2);
+    EXPECT_TRUE(metricProducer2_2->isActive());
 
-    i = 0;
-    for (; i < metricsManager1001->mAllAtomMatchers.size(); i++) {
-        if (metricsManager1001->mAllAtomMatchers[i]->getId() ==
-                metric1ActivationTrigger1->atom_matcher_id()) {
-            break;
-        }
-    }
-    const auto& activation1001_1 = metricProducer1001->mEventActivationMap.at(i);
-    EXPECT_EQ(100 * NS_PER_SEC, activation1001_1->ttl_ns);
-    EXPECT_EQ(0, activation1001_1->start_ns);
-    EXPECT_EQ(kNotActive, activation1001_1->state);
-    EXPECT_EQ(ACTIVATE_ON_BOOT, activation1001_1->activationType);
+    EXPECT_EQ(metricProducer2_1->mEventActivationMap.size(), 2);
+    // The key in mEventActivationMap is the index of the associated atom matcher. We assume
+    // that matchers are indexed in the order that they are added to the config.
+    const auto& activation2_1_1 = metricProducer2_1->mEventActivationMap.at(0);
+    EXPECT_EQ(100 * NS_PER_SEC, activation2_1_1->ttl_ns);
+    EXPECT_EQ(0, activation2_1_1->start_ns);
+    EXPECT_EQ(kNotActive, activation2_1_1->state);
+    EXPECT_EQ(ACTIVATE_ON_BOOT, activation2_1_1->activationType);
 
-    i = 0;
-    for (; i < metricsManager1001->mAllAtomMatchers.size(); i++) {
-        if (metricsManager1001->mAllAtomMatchers[i]->getId() ==
-                metric1ActivationTrigger2->atom_matcher_id()) {
-            break;
-        }
-    }
-
-    const auto& activation1001_2 = metricProducer1001->mEventActivationMap.at(i);
-    EXPECT_EQ(200 * NS_PER_SEC, activation1001_2->ttl_ns);
-    EXPECT_EQ(0, activation1001_2->start_ns);
-    EXPECT_EQ(kNotActive, activation1001_2->state);
-    EXPECT_EQ(ACTIVATE_IMMEDIATELY, activation1001_2->activationType);
+    const auto& activation2_1_2 = metricProducer2_1->mEventActivationMap.at(1);
+    EXPECT_EQ(200 * NS_PER_SEC, activation2_1_2->ttl_ns);
+    EXPECT_EQ(0, activation2_1_2->start_ns);
+    EXPECT_EQ(kNotActive, activation2_1_2->state);
+    EXPECT_EQ(ACTIVATE_IMMEDIATELY, activation2_1_2->activationType);
     // }}}-----------------------------------------------------------------------------------
 
     // Load saved state from disk.
@@ -1350,13 +1308,14 @@
     // Metric 1 active; Activation 1 is active, Activation 2 is not active
     // Metric 2 is active.
     // {{{---------------------------------------------------------------------------
-    EXPECT_TRUE(metricProducer1001->isActive());
-    EXPECT_EQ(timeBase2 + ttl1 - activation1001_1->ttl_ns, activation1001_1->start_ns);
-    EXPECT_EQ(kActive, activation1001_1->state);
-    EXPECT_EQ(0, activation1001_2->start_ns);
-    EXPECT_EQ(kNotActive, activation1001_2->state);
+    EXPECT_TRUE(metricProducer2_1->isActive());
+    int64_t ttl1 = metric1ActivationTrigger1->ttl_seconds() * NS_PER_SEC;
+    EXPECT_EQ(timeBase2 + ttl1 - activation2_1_1->ttl_ns, activation2_1_1->start_ns);
+    EXPECT_EQ(kActive, activation2_1_1->state);
+    EXPECT_EQ(0, activation2_1_2->start_ns);
+    EXPECT_EQ(kNotActive, activation2_1_2->state);
 
-    EXPECT_TRUE(metricProducer1002->isActive());
+    EXPECT_TRUE(metricProducer2_2->isActive());
     // }}}--------------------------------------------------------------------------------
 
     // Trigger Activation 2 for Metric 1.
@@ -1369,23 +1328,23 @@
     // Metric 1 active; Activation 1 is active, Activation 2 is active
     // Metric 2 is active.
     // {{{---------------------------------------------------------------------------
-    EXPECT_TRUE(metricProducer1001->isActive());
-    EXPECT_EQ(timeBase2 + ttl1 - activation1001_1->ttl_ns, activation1001_1->start_ns);
-    EXPECT_EQ(kActive, activation1001_1->state);
-    EXPECT_EQ(screenOnEvent->GetElapsedTimestampNs(), activation1001_2->start_ns);
-    EXPECT_EQ(kActive, activation1001_2->state);
+    EXPECT_TRUE(metricProducer2_1->isActive());
+    EXPECT_EQ(timeBase2 + ttl1 - activation2_1_1->ttl_ns, activation2_1_1->start_ns);
+    EXPECT_EQ(kActive, activation2_1_1->state);
+    EXPECT_EQ(screenOnEvent->GetElapsedTimestampNs(), activation2_1_2->start_ns);
+    EXPECT_EQ(kActive, activation2_1_2->state);
 
-    EXPECT_TRUE(metricProducer1002->isActive());
+    EXPECT_TRUE(metricProducer2_2->isActive());
     // }}}---------------------------------------------------------------------------
 
     // Simulate shutdown by saving state to disk
     shutDownTime = timeBase2 + 50 * NS_PER_SEC;
     processor2->SaveActiveConfigsToDisk(shutDownTime);
-    EXPECT_TRUE(metricProducer1001->isActive());
-    EXPECT_TRUE(metricProducer1002->isActive());
-    ttl1 = timeBase2 + metric1ActivationTrigger1->ttl_seconds() * NS_PER_SEC - shutDownTime;
-    int64_t ttl2 = screenOnEvent->GetElapsedTimestampNs() +
-            metric1ActivationTrigger2->ttl_seconds() * NS_PER_SEC - shutDownTime;
+    EXPECT_TRUE(metricProducer2_1->isActive());
+    EXPECT_TRUE(metricProducer2_2->isActive());
+    ttl1 -= shutDownTime - timeBase2;
+    int64_t ttl2 = metric1ActivationTrigger2->ttl_seconds() * NS_PER_SEC
+            - (shutDownTime - screenOnEvent->GetElapsedTimestampNs());
 
     // Simulate device restarted state by creating new instance of StatsLogProcessor with the
     // same config.
@@ -1399,55 +1358,34 @@
     EXPECT_EQ(1, processor3->mMetricsManagers.size());
     it = processor3->mMetricsManagers.find(cfgKey1);
     EXPECT_TRUE(it != processor3->mMetricsManagers.end());
-    auto& metricsManagerTimeBase3 = it->second;
-    EXPECT_TRUE(metricsManagerTimeBase3->isActive());
+    auto& metricsManager3 = it->second;
+    EXPECT_TRUE(metricsManager3->isActive());
 
-    metricIt = metricsManagerTimeBase3->mAllMetricProducers.begin();
-    for (; metricIt != metricsManagerTimeBase3->mAllMetricProducers.end(); metricIt++) {
-        if ((*metricIt)->getMetricId() == metricId1) {
-            break;
-        }
-    }
-    EXPECT_TRUE(metricIt != metricsManagerTimeBase3->mAllMetricProducers.end());
-    auto& metricProducerTimeBase3_1 = *metricIt;
-    EXPECT_FALSE(metricProducerTimeBase3_1->isActive());
+    EXPECT_EQ(metricsManager3->mAllMetricProducers.size(), 2);
+    // We assume that the index of a MetricProducer within the mAllMetricProducers
+    // array follows the order in which metrics are added to the config.
+    auto& metricProducer3_1 = metricsManager3->mAllMetricProducers[0];
+    EXPECT_EQ(metricProducer3_1->getMetricId(), metricId1);
+    EXPECT_FALSE(metricProducer3_1->isActive());
 
-    metricIt = metricsManagerTimeBase3->mAllMetricProducers.begin();
-    for (; metricIt != metricsManagerTimeBase3->mAllMetricProducers.end(); metricIt++) {
-        if ((*metricIt)->getMetricId() == metricId2) {
-            break;
-        }
-    }
-    EXPECT_TRUE(metricIt != metricsManagerTimeBase3->mAllMetricProducers.end());
-    auto& metricProducerTimeBase3_2 = *metricIt;
-    EXPECT_TRUE(metricProducerTimeBase3_2->isActive());
+    auto& metricProducer3_2 = metricsManager3->mAllMetricProducers[1];
+    EXPECT_EQ(metricProducer3_2->getMetricId(), metricId2);
+    EXPECT_TRUE(metricProducer3_2->isActive());
 
-    i = 0;
-    for (; i < metricsManagerTimeBase3->mAllAtomMatchers.size(); i++) {
-        if (metricsManagerTimeBase3->mAllAtomMatchers[i]->getId() ==
-                metric1ActivationTrigger1->atom_matcher_id()) {
-            break;
-        }
-    }
-    const auto& activationTimeBase3_1 = metricProducerTimeBase3_1->mEventActivationMap.at(i);
-    EXPECT_EQ(100 * NS_PER_SEC, activationTimeBase3_1->ttl_ns);
-    EXPECT_EQ(0, activationTimeBase3_1->start_ns);
-    EXPECT_EQ(kNotActive, activationTimeBase3_1->state);
-    EXPECT_EQ(ACTIVATE_ON_BOOT, activationTimeBase3_1->activationType);
+    EXPECT_EQ(metricProducer3_1->mEventActivationMap.size(), 2);
+    // The key in mEventActivationMap is the index of the associated atom matcher. We assume
+    // that matchers are indexed in the order that they are added to the config.
+    const auto& activation3_1_1 = metricProducer3_1->mEventActivationMap.at(0);
+    EXPECT_EQ(100 * NS_PER_SEC, activation3_1_1->ttl_ns);
+    EXPECT_EQ(0, activation3_1_1->start_ns);
+    EXPECT_EQ(kNotActive, activation3_1_1->state);
+    EXPECT_EQ(ACTIVATE_ON_BOOT, activation3_1_1->activationType);
 
-    i = 0;
-    for (; i < metricsManagerTimeBase3->mAllAtomMatchers.size(); i++) {
-        if (metricsManagerTimeBase3->mAllAtomMatchers[i]->getId() ==
-                metric1ActivationTrigger2->atom_matcher_id()) {
-            break;
-        }
-    }
-
-    const auto& activationTimeBase3_2 = metricProducerTimeBase3_1->mEventActivationMap.at(i);
-    EXPECT_EQ(200 * NS_PER_SEC, activationTimeBase3_2->ttl_ns);
-    EXPECT_EQ(0, activationTimeBase3_2->start_ns);
-    EXPECT_EQ(kNotActive, activationTimeBase3_2->state);
-    EXPECT_EQ(ACTIVATE_IMMEDIATELY, activationTimeBase3_2->activationType);
+    const auto& activation3_1_2 = metricProducer3_1->mEventActivationMap.at(1);
+    EXPECT_EQ(200 * NS_PER_SEC, activation3_1_2->ttl_ns);
+    EXPECT_EQ(0, activation3_1_2->start_ns);
+    EXPECT_EQ(kNotActive, activation3_1_2->state);
+    EXPECT_EQ(ACTIVATE_IMMEDIATELY, activation3_1_2->activationType);
     // }}}----------------------------------------------------------------------------------
 
     // Load saved state from disk.
@@ -1456,13 +1394,13 @@
     // Metric 1 active: Activation 1 is active, Activation 2 is active
     // Metric 2 is active.
     // {{{---------------------------------------------------------------------------
-    EXPECT_TRUE(metricProducerTimeBase3_1->isActive());
-    EXPECT_EQ(timeBase3 + ttl1 - activationTimeBase3_1->ttl_ns, activationTimeBase3_1->start_ns);
-    EXPECT_EQ(kActive, activationTimeBase3_1->state);
-    EXPECT_EQ(timeBase3 + ttl2 - activationTimeBase3_2->ttl_ns, activationTimeBase3_2->start_ns);
-    EXPECT_EQ(kActive, activationTimeBase3_2->state);
+    EXPECT_TRUE(metricProducer3_1->isActive());
+    EXPECT_EQ(timeBase3 + ttl1 - activation3_1_1->ttl_ns, activation3_1_1->start_ns);
+    EXPECT_EQ(kActive, activation3_1_1->state);
+    EXPECT_EQ(timeBase3 + ttl2 - activation3_1_2->ttl_ns, activation3_1_2->start_ns);
+    EXPECT_EQ(kActive, activation3_1_2->state);
 
-    EXPECT_TRUE(metricProducerTimeBase3_2->isActive());
+    EXPECT_TRUE(metricProducer3_2->isActive());
     // }}}-------------------------------------------------------------------------------
 
 
@@ -1473,15 +1411,16 @@
     );
     processor3->OnLogEvent(screenOnEvent.get());
 
-    // Metric 1 active; Activation 1 is not active, Activation 2 is set to active
+    // Metric 1 active; Activation 1 is inactive (above screenOnEvent causes ttl1 to expire),
+    //                  Activation 2 is set to active
     // Metric 2 is active.
     // {{{---------------------------------------------------------------------------
-    EXPECT_TRUE(metricProducerTimeBase3_1->isActive());
-    EXPECT_EQ(kNotActive, activationTimeBase3_1->state);
-    EXPECT_EQ(screenOnEvent->GetElapsedTimestampNs(), activationTimeBase3_2->start_ns);
-    EXPECT_EQ(kActive, activationTimeBase3_2->state);
+    EXPECT_TRUE(metricProducer3_1->isActive());
+    EXPECT_EQ(kNotActive, activation3_1_1->state);
+    EXPECT_EQ(screenOnEvent->GetElapsedTimestampNs(), activation3_1_2->start_ns);
+    EXPECT_EQ(kActive, activation3_1_2->state);
 
-    EXPECT_TRUE(metricProducerTimeBase3_2->isActive());
+    EXPECT_TRUE(metricProducer3_2->isActive());
     // }}}---------------------------------------------------------------------------
 }
 
diff --git a/cmds/statsd/tests/metrics/GaugeMetricProducer_test.cpp b/cmds/statsd/tests/metrics/GaugeMetricProducer_test.cpp
index 47c21aa..b027e8e 100644
--- a/cmds/statsd/tests/metrics/GaugeMetricProducer_test.cpp
+++ b/cmds/statsd/tests/metrics/GaugeMetricProducer_test.cpp
@@ -79,8 +79,6 @@
                                       logEventMatcherIndex, eventMatcherWizard,
                                       -1, -1, tagId, 5, 600 * NS_PER_SEC + NS_PER_SEC / 2,
                                       pullerManager);
-    gaugeProducer.prepareFirstBucket();
-
 
     EXPECT_EQ(600500000000, gaugeProducer.mCurrentBucketStartTimeNs);
     EXPECT_EQ(10, gaugeProducer.mCurrentBucketNum);
@@ -126,8 +124,6 @@
                                       tagId, -1, tagId, bucketStartTimeNs, bucketStartTimeNs,
                                       pullerManager);
 
-    gaugeProducer.prepareFirstBucket();
-
     vector<shared_ptr<LogEvent>> allData;
     allData.clear();
     shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucket2StartTimeNs + 1);
@@ -211,7 +207,6 @@
                                       logEventMatcherIndex, eventMatcherWizard,
                                       -1 /* -1 means no pulling */, -1, tagId, bucketStartTimeNs,
                                       bucketStartTimeNs, pullerManager);
-    gaugeProducer.prepareFirstBucket();
 
     sp<AnomalyTracker> anomalyTracker = gaugeProducer.addAnomalyTracker(alert, alarmMonitor);
     EXPECT_TRUE(anomalyTracker != nullptr);
@@ -303,7 +298,6 @@
     GaugeMetricProducer gaugeProducer(kConfigKey, metric, -1 /*-1 meaning no condition*/, wizard,
                                       logEventMatcherIndex, eventMatcherWizard, tagId, -1, tagId,
                                       bucketStartTimeNs, bucketStartTimeNs, pullerManager);
-    gaugeProducer.prepareFirstBucket();
 
     vector<shared_ptr<LogEvent>> allData;
     shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucketStartTimeNs + 1);
@@ -370,7 +364,6 @@
                                       logEventMatcherIndex, eventMatcherWizard,
                                       tagId, -1, tagId, bucketStartTimeNs, bucketStartTimeNs,
                                       pullerManager);
-    gaugeProducer.prepareFirstBucket();
 
     vector<shared_ptr<LogEvent>> allData;
     shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucketStartTimeNs + 1);
@@ -431,7 +424,6 @@
     GaugeMetricProducer gaugeProducer(kConfigKey, metric, 1, wizard,
                                       logEventMatcherIndex, eventMatcherWizard, tagId, -1, tagId,
                                       bucketStartTimeNs, bucketStartTimeNs, pullerManager);
-    gaugeProducer.prepareFirstBucket();
 
     gaugeProducer.onConditionChanged(true, bucketStartTimeNs + 8);
     EXPECT_EQ(1UL, gaugeProducer.mCurrentSlicedBucket->size());
@@ -521,7 +513,6 @@
     GaugeMetricProducer gaugeProducer(kConfigKey, metric, 1, wizard,
                                       logEventMatcherIndex, eventMatcherWizard, tagId, -1, tagId,
                                       bucketStartTimeNs, bucketStartTimeNs, pullerManager);
-    gaugeProducer.prepareFirstBucket();
 
     gaugeProducer.onSlicedConditionMayChange(true, bucketStartTimeNs + 8);
 
@@ -572,7 +563,6 @@
                                       logEventMatcherIndex, eventMatcherWizard,
                                       tagId, -1, tagId, bucketStartTimeNs, bucketStartTimeNs,
                                       pullerManager);
-    gaugeProducer.prepareFirstBucket();
 
     Alert alert;
     alert.set_id(101);
@@ -681,7 +671,6 @@
                                       logEventMatcherIndex, eventMatcherWizard,
                                       tagId, triggerId, tagId, bucketStartTimeNs, bucketStartTimeNs,
                                       pullerManager);
-    gaugeProducer.prepareFirstBucket();
 
     vector<shared_ptr<LogEvent>> allData;
 
@@ -766,7 +755,6 @@
                                       logEventMatcherIndex, eventMatcherWizard,
                                       tagId, triggerId, tagId, bucketStartTimeNs, bucketStartTimeNs,
                                       pullerManager);
-    gaugeProducer.prepareFirstBucket();
 
     vector<shared_ptr<LogEvent>> allData;
 
diff --git a/cmds/statsd/tests/metrics/ValueMetricProducer_test.cpp b/cmds/statsd/tests/metrics/ValueMetricProducer_test.cpp
index 2262c76..4b9d0c0 100644
--- a/cmds/statsd/tests/metrics/ValueMetricProducer_test.cpp
+++ b/cmds/statsd/tests/metrics/ValueMetricProducer_test.cpp
@@ -105,7 +105,6 @@
                 kConfigKey, metric, -1 /*-1 meaning no condition*/, wizard,
                 logEventMatcherIndex, eventMatcherWizard, tagId,
                 bucketStartTimeNs, bucketStartTimeNs, pullerManager);
-        valueProducer->prepareFirstBucket();
         return valueProducer;
     }
 
@@ -125,7 +124,6 @@
                 new ValueMetricProducer(kConfigKey, metric, 1, wizard, logEventMatcherIndex,
                                         eventMatcherWizard, tagId, bucketStartTimeNs,
                                         bucketStartTimeNs, pullerManager);
-        valueProducer->prepareFirstBucket();
         valueProducer->mCondition = ConditionState::kFalse;
         return valueProducer;
     }
@@ -169,7 +167,6 @@
     ValueMetricProducer valueProducer(kConfigKey, metric, -1 /*-1 meaning no condition*/, wizard,
                                       logEventMatcherIndex, eventMatcherWizard, -1, startTimeBase,
                                       22, pullerManager);
-    valueProducer.prepareFirstBucket();
 
     EXPECT_EQ(startTimeBase, valueProducer.calcPreviousBucketEndTime(60 * NS_PER_SEC + 10));
     EXPECT_EQ(startTimeBase, valueProducer.calcPreviousBucketEndTime(60 * NS_PER_SEC + 10));
@@ -199,7 +196,6 @@
     ValueMetricProducer valueProducer(kConfigKey, metric, -1 /*-1 meaning no condition*/, wizard,
                                       logEventMatcherIndex, eventMatcherWizard, -1, 5,
                                       600 * NS_PER_SEC + NS_PER_SEC / 2, pullerManager);
-    valueProducer.prepareFirstBucket();
 
     EXPECT_EQ(600500000000, valueProducer.mCurrentBucketStartTimeNs);
     EXPECT_EQ(10, valueProducer.mCurrentBucketNum);
@@ -381,7 +377,6 @@
             kConfigKey, metric, -1 /*-1 meaning no condition*/, wizard,
             logEventMatcherIndex, eventMatcherWizard, tagId,
             bucketStartTimeNs, bucketStartTimeNs, pullerManager);
-    valueProducer->prepareFirstBucket();
 
     vector<shared_ptr<LogEvent>> allData;
     allData.clear();
@@ -670,7 +665,6 @@
     ValueMetricProducer valueProducer(kConfigKey, metric, -1, wizard, logEventMatcherIndex,
                                       eventMatcherWizard, -1, bucketStartTimeNs, bucketStartTimeNs,
                                       pullerManager);
-    valueProducer.prepareFirstBucket();
 
     shared_ptr<LogEvent> event1 = make_shared<LogEvent>(tagId, bucketStartTimeNs + 10);
     event1->write(1);
@@ -728,7 +722,6 @@
     ValueMetricProducer valueProducer(kConfigKey, metric, -1, wizard, logEventMatcherIndex,
                                       eventMatcherWizard, tagId, bucketStartTimeNs,
                                       bucketStartTimeNs, pullerManager);
-    valueProducer.prepareFirstBucket();
 
     vector<shared_ptr<LogEvent>> allData;
     allData.clear();
@@ -779,7 +772,6 @@
     ValueMetricProducer valueProducer(kConfigKey, metric, -1, wizard, logEventMatcherIndex,
                                       eventMatcherWizard, tagId, bucketStartTimeNs,
                                       bucketStartTimeNs, pullerManager);
-    valueProducer.prepareFirstBucket();
 
     vector<shared_ptr<LogEvent>> allData;
     allData.clear();
@@ -854,7 +846,6 @@
     ValueMetricProducer valueProducer(kConfigKey, metric, -1, wizard, logEventMatcherIndex,
                                       eventMatcherWizard, -1, bucketStartTimeNs, bucketStartTimeNs,
                                       pullerManager);
-    valueProducer.prepareFirstBucket();
 
     shared_ptr<LogEvent> event1 = make_shared<LogEvent>(tagId, bucketStartTimeNs + 10);
     event1->write(1);
@@ -897,7 +888,6 @@
     ValueMetricProducer valueProducer(kConfigKey, metric, 1, wizard, logEventMatcherIndex,
                                       eventMatcherWizard, -1, bucketStartTimeNs, bucketStartTimeNs,
                                       pullerManager);
-    valueProducer.prepareFirstBucket();
     valueProducer.mCondition = ConditionState::kFalse;
 
     shared_ptr<LogEvent> event1 = make_shared<LogEvent>(tagId, bucketStartTimeNs + 10);
@@ -972,7 +962,6 @@
     ValueMetricProducer valueProducer(kConfigKey, metric, -1 /*-1 meaning no condition*/, wizard,
                                       logEventMatcherIndex, eventMatcherWizard, -1 /*not pulled*/,
                                       bucketStartTimeNs, bucketStartTimeNs, pullerManager);
-    valueProducer.prepareFirstBucket();
 
     sp<AnomalyTracker> anomalyTracker = valueProducer.addAnomalyTracker(alert, alarmMonitor);
 
@@ -1269,7 +1258,6 @@
     ValueMetricProducer valueProducer(kConfigKey, metric, -1, wizard, logEventMatcherIndex,
                                       eventMatcherWizard, -1, bucketStartTimeNs, bucketStartTimeNs,
                                       pullerManager);
-    valueProducer.prepareFirstBucket();
 
     shared_ptr<LogEvent> event1 = make_shared<LogEvent>(tagId, bucketStartTimeNs + 10);
     event1->write(1);
@@ -1314,7 +1302,6 @@
     ValueMetricProducer valueProducer(kConfigKey, metric, -1, wizard, logEventMatcherIndex,
                                       eventMatcherWizard, -1, bucketStartTimeNs, bucketStartTimeNs,
                                       pullerManager);
-    valueProducer.prepareFirstBucket();
 
     shared_ptr<LogEvent> event1 = make_shared<LogEvent>(tagId, bucketStartTimeNs + 10);
     event1->write(1);
@@ -1361,7 +1348,6 @@
     ValueMetricProducer valueProducer(kConfigKey, metric, -1, wizard, logEventMatcherIndex,
                                       eventMatcherWizard, -1, bucketStartTimeNs, bucketStartTimeNs,
                                       pullerManager);
-    valueProducer.prepareFirstBucket();
 
     shared_ptr<LogEvent> event1 = make_shared<LogEvent>(tagId, bucketStartTimeNs + 10);
     event1->write(1);
@@ -1412,7 +1398,6 @@
     ValueMetricProducer valueProducer(kConfigKey, metric, -1, wizard, logEventMatcherIndex,
                                       eventMatcherWizard, -1, bucketStartTimeNs, bucketStartTimeNs,
                                       pullerManager);
-    valueProducer.prepareFirstBucket();
 
     shared_ptr<LogEvent> event1 = make_shared<LogEvent>(tagId, bucketStartTimeNs + 10);
     event1->write(1);
@@ -1458,7 +1443,6 @@
     ValueMetricProducer valueProducer(kConfigKey, metric, -1, wizard, logEventMatcherIndex,
                                       eventMatcherWizard, -1, bucketStartTimeNs, bucketStartTimeNs,
                                       pullerManager);
-    valueProducer.prepareFirstBucket();
 
     shared_ptr<LogEvent> event1 = make_shared<LogEvent>(tagId, bucketStartTimeNs + 10);
     event1->write(1);
@@ -1532,7 +1516,6 @@
     ValueMetricProducer valueProducer(kConfigKey, metric, -1, wizard, logEventMatcherIndex,
                                       eventMatcherWizard, -1, bucketStartTimeNs, bucketStartTimeNs,
                                       pullerManager);
-    valueProducer.prepareFirstBucket();
 
     shared_ptr<LogEvent> event1 = make_shared<LogEvent>(tagId, bucketStartTimeNs + 10);
     event1->write(1);
@@ -2081,7 +2064,6 @@
     ValueMetricProducer valueProducer(kConfigKey, metric, 1, wizard, logEventMatcherIndex,
                                       eventMatcherWizard, tagId, bucket2StartTimeNs,
                                       bucket2StartTimeNs, pullerManager);
-    valueProducer.prepareFirstBucket();
     valueProducer.mCondition = ConditionState::kFalse;
 
     // Event should be skipped since it is from previous bucket.
@@ -2862,7 +2844,6 @@
     ValueMetricProducer valueProducer(kConfigKey, metric, -1, wizard, logEventMatcherIndex,
                                       eventMatcherWizard, tagId, bucketStartTimeNs,
                                       bucketStartTimeNs, pullerManager);
-    valueProducer.prepareFirstBucket();
 
     ProtoOutputStream output;
     std::set<string> strSet;
@@ -2905,7 +2886,6 @@
     ValueMetricProducer valueProducer(kConfigKey, metric, -1, wizard, logEventMatcherIndex,
                                       eventMatcherWizard, tagId, bucketStartTimeNs,
                                       bucketStartTimeNs, pullerManager);
-    valueProducer.prepareFirstBucket();
 
     vector<shared_ptr<LogEvent>> allData;
     allData.clear();
@@ -2969,7 +2949,6 @@
     ValueMetricProducer valueProducer(kConfigKey, metric, -1, wizard, logEventMatcherIndex,
                                       eventMatcherWizard, tagId, bucketStartTimeNs,
                                       bucketStartTimeNs, pullerManager);
-    valueProducer.prepareFirstBucket();
 
     ProtoOutputStream output;
     std::set<string> strSet;
diff --git a/core/java/android/accessibilityservice/AccessibilityService.java b/core/java/android/accessibilityservice/AccessibilityService.java
index d3c274f..4603f08 100644
--- a/core/java/android/accessibilityservice/AccessibilityService.java
+++ b/core/java/android/accessibilityservice/AccessibilityService.java
@@ -605,7 +605,7 @@
     }
 
     /**
-     * Gets the windows on the screen. This method returns only the windows
+     * Gets the windows on the screen of the default display. This method returns only the windows
      * that a sighted user can interact with, as opposed to all windows.
      * For example, if there is a modal dialog shown and the user cannot touch
      * anything behind it, then only the modal window will be reported
@@ -632,6 +632,34 @@
     }
 
     /**
+     * Gets the windows on the screen of all displays. This method returns only the windows
+     * that a sighted user can interact with, as opposed to all windows.
+     * For example, if there is a modal dialog shown and the user cannot touch
+     * anything behind it, then only the modal window will be reported
+     * (assuming it is the top one). For convenience the returned windows
+     * are ordered in a descending layer order, which is the windows that
+     * are on top are reported first. Since the user can always
+     * interact with the window that has input focus by typing, the focused
+     * window is always returned (even if covered by a modal window).
+     * <p>
+     * <strong>Note:</strong> In order to access the windows your service has
+     * to declare the capability to retrieve window content by setting the
+     * {@link android.R.styleable#AccessibilityService_canRetrieveWindowContent}
+     * property in its meta-data. For details refer to {@link #SERVICE_META_DATA}.
+     * Also the service has to opt-in to retrieve the interactive windows by
+     * setting the {@link AccessibilityServiceInfo#FLAG_RETRIEVE_INTERACTIVE_WINDOWS}
+     * flag.
+     * </p>
+     *
+     * @return The windows of all displays if there are windows and the service is can retrieve
+     *         them, otherwise an empty list. The key of SparseArray is display ID.
+     */
+    @NonNull
+    public final SparseArray<List<AccessibilityWindowInfo>> getWindowsOnAllDisplays() {
+        return AccessibilityInteractionClient.getInstance().getWindowsOnAllDisplays(mConnectionId);
+    }
+
+    /**
      * Gets the root node in the currently active window if this service
      * can retrieve window content. The active window is the one that the user
      * is currently touching or the window with input focus, if the user is not
diff --git a/core/java/android/accessibilityservice/AccessibilityShortcutInfo.java b/core/java/android/accessibilityservice/AccessibilityShortcutInfo.java
new file mode 100644
index 0000000..f4cadfd
--- /dev/null
+++ b/core/java/android/accessibilityservice/AccessibilityShortcutInfo.java
@@ -0,0 +1,225 @@
+/*
+ * 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.accessibilityservice;
+
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.content.ComponentName;
+import android.content.Context;
+import android.content.Intent;
+import android.content.pm.ActivityInfo;
+import android.content.pm.PackageManager;
+import android.content.res.Resources;
+import android.content.res.TypedArray;
+import android.content.res.XmlResourceParser;
+import android.util.AttributeSet;
+import android.util.Xml;
+
+import org.xmlpull.v1.XmlPullParser;
+import org.xmlpull.v1.XmlPullParserException;
+
+import java.io.IOException;
+
+/**
+ * Activities of interest to users with accessibility needs may request to be targets of the
+ * accessibility shortcut. These activities must handle the
+ * {@link Intent#ACTION_MAIN} intent with category
+ * {@link Intent#CATEGORY_ACCESSIBILITY_SHORTCUT_TARGET}, which will be dispatched by the system
+ * when the user activates the shortcut when it is configured to point at this target.
+ *
+ * @see Intent#CATEGORY_ACCESSIBILITY_SHORTCUT_TARGET
+ *
+ * @hide
+ */
+public final class AccessibilityShortcutInfo {
+    private static final String TAG_ACCESSIBILITY_SHORTCUT = "accessibility-shortcut-target";
+
+    /**
+     * Name under which an activity component of the accessibility shortcut publishes information
+     * about itself. This meta-data must reference an XML resource containing an
+     * <code>&lt;accessibility-shortcut-target&gt;</code> tag.
+     */
+    public static final String META_DATA = "android.accessibilityshortcut.target";
+
+    /**
+     * The component name of the accessibility shortcut target.
+     */
+    private final ComponentName mComponentName;
+
+    /**
+     * The activity info of the accessibility shortcut target.
+     */
+    private final ActivityInfo mActivityInfo;
+
+    /**
+     * Resource id of the summary of the accessibility shortcut target.
+     */
+    private final int mSummaryResId;
+
+    /**
+     * Resource id of the description of the accessibility shortcut target.
+     */
+    private final int mDescriptionResId;
+
+    /**
+     * Creates a new instance.
+     *
+     * @param context Context for accessing resources.
+     * @param activityInfo The activity info.
+     * @throws XmlPullParserException If a XML parsing error occurs.
+     * @throws IOException If a XML parsing error occurs.
+     */
+    public AccessibilityShortcutInfo(@NonNull Context context, @NonNull ActivityInfo activityInfo)
+            throws XmlPullParserException, IOException {
+        final PackageManager packageManager = context.getPackageManager();
+        mComponentName = activityInfo.getComponentName();
+        mActivityInfo = activityInfo;
+
+        try (XmlResourceParser parser = mActivityInfo.loadXmlMetaData(
+                packageManager, META_DATA)) {
+            if (parser == null) {
+                throw new XmlPullParserException("Meta-data "
+                        + TAG_ACCESSIBILITY_SHORTCUT + " does not exist");
+            }
+
+            int type = 0;
+            while (type != XmlPullParser.END_DOCUMENT && type != XmlPullParser.START_TAG) {
+                type = parser.next();
+            }
+
+            final String nodeName = parser.getName();
+            if (!TAG_ACCESSIBILITY_SHORTCUT.equals(nodeName)) {
+                throw new XmlPullParserException("Meta-data does not start with"
+                        + TAG_ACCESSIBILITY_SHORTCUT + " tag");
+            }
+
+            final AttributeSet allAttributes = Xml.asAttributeSet(parser);
+            final Resources resources = packageManager.getResourcesForApplication(
+                    mActivityInfo.applicationInfo);
+            final TypedArray asAttributes = resources.obtainAttributes(allAttributes,
+                    com.android.internal.R.styleable.AccessibilityShortcutTarget);
+
+            // Gets description
+            mDescriptionResId = asAttributes.getResourceId(
+                    com.android.internal.R.styleable.AccessibilityShortcutTarget_description, 0);
+            // Gets summary
+            mSummaryResId = asAttributes.getResourceId(
+                    com.android.internal.R.styleable.AccessibilityShortcutTarget_summary, 0);
+            asAttributes.recycle();
+
+            if (mDescriptionResId == 0 || mSummaryResId == 0) {
+                throw new XmlPullParserException("No description or summary in meta-data");
+            }
+        } catch (PackageManager.NameNotFoundException e) {
+            throw new XmlPullParserException("Unable to create context for: "
+                    + mActivityInfo.packageName);
+        }
+    }
+
+    /**
+     * The {@link ActivityInfo} of accessibility shortcut target.
+     *
+     * @return The activity info.
+     */
+    @NonNull
+    public ActivityInfo getActivityInfo() {
+        return mActivityInfo;
+    }
+
+    /**
+     * The localized summary of the accessibility shortcut target.
+     *
+     * @return The localized summary if available, and {@code null} if a summary
+     * has not been provided.
+     */
+    @Nullable
+    public String loadSummary(@NonNull PackageManager packageManager) {
+        return loadResourceString(packageManager, mActivityInfo, mSummaryResId);
+    }
+
+    /**
+     * The localized description of the accessibility shortcut target.
+     *
+     * @return The localized description.
+     */
+    @Nullable
+    public String loadDescription(@NonNull PackageManager packageManager) {
+        return loadResourceString(packageManager, mActivityInfo, mDescriptionResId);
+    }
+
+    /**
+     * Gets string resource by the given activity and resource id.
+     */
+    @Nullable
+    private String loadResourceString(@NonNull PackageManager packageManager,
+            @NonNull ActivityInfo activityInfo, int resId) {
+        if (resId == 0) {
+            return null;
+        }
+        final CharSequence text = packageManager.getText(activityInfo.packageName,
+                resId, activityInfo.applicationInfo);
+        if (text != null) {
+            return text.toString().trim();
+        }
+        return null;
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    public int hashCode() {
+        return 31 * 1 + ((mComponentName == null) ? 0 : mComponentName.hashCode());
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    public boolean equals(Object obj) {
+        if (this == obj) {
+            return true;
+        }
+        if (obj == null) {
+            return false;
+        }
+        if (getClass() != obj.getClass()) {
+            return false;
+        }
+        final AccessibilityShortcutInfo other = (AccessibilityShortcutInfo) obj;
+        if (mComponentName == null) {
+            if (other.mComponentName != null) {
+                return false;
+            }
+        } else if (!mComponentName.equals(other.mComponentName)) {
+            return false;
+        }
+        return true;
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    public String toString() {
+        StringBuilder stringBuilder = new StringBuilder();
+        stringBuilder.append("AccessibilityShortcutInfo[");
+        stringBuilder.append("activityInfo: ").append(mActivityInfo);
+        stringBuilder.append("]");
+        return stringBuilder.toString();
+    }
+}
diff --git a/core/java/android/accessibilityservice/IAccessibilityServiceConnection.aidl b/core/java/android/accessibilityservice/IAccessibilityServiceConnection.aidl
index 1ca07dd..4841781 100644
--- a/core/java/android/accessibilityservice/IAccessibilityServiceConnection.aidl
+++ b/core/java/android/accessibilityservice/IAccessibilityServiceConnection.aidl
@@ -60,7 +60,7 @@
 
     AccessibilityWindowInfo getWindow(int windowId);
 
-    List<AccessibilityWindowInfo> getWindows();
+    AccessibilityWindowInfo.WindowListSparseArray getWindows();
 
     AccessibilityServiceInfo getServiceInfo();
 
diff --git a/core/java/android/app/Activity.java b/core/java/android/app/Activity.java
index cf36032..03300e4 100644
--- a/core/java/android/app/Activity.java
+++ b/core/java/android/app/Activity.java
@@ -76,7 +76,6 @@
 import android.os.RemoteException;
 import android.os.ServiceManager.ServiceNotFoundException;
 import android.os.StrictMode;
-import android.os.SystemProperties;
 import android.os.Trace;
 import android.os.UserHandle;
 import android.text.Selection;
@@ -7866,13 +7865,10 @@
         mFragments.dispatchStart();
         mFragments.reportLoaderStart();
 
+        // Warn app developers if the dynamic linker logged anything during startup.
         boolean isAppDebuggable =
                 (mApplication.getApplicationInfo().flags & ApplicationInfo.FLAG_DEBUGGABLE) != 0;
-
-        // This property is set for all non-user builds except final release
-        boolean isDlwarningEnabled = SystemProperties.getInt("ro.bionic.ld.warning", 0) == 1;
-
-        if (isAppDebuggable || isDlwarningEnabled) {
+        if (isAppDebuggable) {
             String dlwarning = getDlWarning();
             if (dlwarning != null) {
                 String appName = getApplicationInfo().loadLabel(getPackageManager())
diff --git a/core/java/android/app/ActivityThread.java b/core/java/android/app/ActivityThread.java
index 38aac1b..7f27368 100644
--- a/core/java/android/app/ActivityThread.java
+++ b/core/java/android/app/ActivityThread.java
@@ -1163,6 +1163,10 @@
             sendMessage(H.ATTACH_AGENT, agent);
         }
 
+        public void attachStartupAgents(String dataDir) {
+            sendMessage(H.ATTACH_STARTUP_AGENTS, dataDir);
+        }
+
         public void setSchedulingGroup(int group) {
             // Note: do this immediately, since going into the foreground
             // should happen regardless of what pending work we have to do
@@ -1812,6 +1816,7 @@
         public static final int EXECUTE_TRANSACTION = 159;
         public static final int RELAUNCH_ACTIVITY = 160;
         public static final int PURGE_RESOURCES = 161;
+        public static final int ATTACH_STARTUP_AGENTS = 162;
 
         String codeToString(int code) {
             if (DEBUG_MESSAGES) {
@@ -1855,6 +1860,7 @@
                     case EXECUTE_TRANSACTION: return "EXECUTE_TRANSACTION";
                     case RELAUNCH_ACTIVITY: return "RELAUNCH_ACTIVITY";
                     case PURGE_RESOURCES: return "PURGE_RESOURCES";
+                    case ATTACH_STARTUP_AGENTS: return "ATTACH_STARTUP_AGENTS";
                 }
             }
             return Integer.toString(code);
@@ -2043,6 +2049,9 @@
                 case PURGE_RESOURCES:
                     schedulePurgeIdler();
                     break;
+                case ATTACH_STARTUP_AGENTS:
+                    handleAttachStartupAgents((String) msg.obj);
+                    break;
             }
             Object obj = msg.obj;
             if (obj instanceof SomeArgs) {
@@ -3779,6 +3788,27 @@
         }
     }
 
+    static void handleAttachStartupAgents(String dataDir) {
+        try {
+            Path code_cache = ContextImpl.getCodeCacheDirBeforeBind(new File(dataDir)).toPath();
+            if (!Files.exists(code_cache)) {
+                return;
+            }
+            Path startup_path = code_cache.resolve("startup_agents");
+            if (Files.exists(startup_path)) {
+                for (Path p : Files.newDirectoryStream(startup_path)) {
+                    handleAttachAgent(
+                            p.toAbsolutePath().toString()
+                            + "="
+                            + dataDir,
+                            null);
+                }
+            }
+        } catch (Exception e) {
+            // Ignored.
+        }
+    }
+
     private static final ThreadLocal<Intent> sCurrentBroadcastIntent = new ThreadLocal<Intent>();
 
     /**
@@ -6427,26 +6457,6 @@
         NetworkSecurityConfigProvider.install(appContext);
         Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
 
-
-        if (isAppDebuggable) {
-            try {
-                // Load all the agents in the code_cache/startup_agents directory.
-                // We pass the absolute path to the data_dir as an argument.
-                Path startup_path = appContext.getCodeCacheDir().toPath().resolve("startup_agents");
-                if (Files.exists(startup_path)) {
-                    for (Path p : Files.newDirectoryStream(startup_path)) {
-                        handleAttachAgent(
-                                p.toAbsolutePath().toString()
-                                + "="
-                                + appContext.getDataDir().toPath().toAbsolutePath().toString(),
-                                data.info);
-                    }
-                }
-            } catch (Exception e) {
-                // Ignored.
-            }
-        }
-
         // Continue loading instrumentation.
         if (ii != null) {
             ApplicationInfo instrApp;
diff --git a/core/java/android/app/ActivityView.java b/core/java/android/app/ActivityView.java
index b56c00e..fbf1f59 100644
--- a/core/java/android/app/ActivityView.java
+++ b/core/java/android/app/ActivityView.java
@@ -22,6 +22,7 @@
 import static android.view.Display.INVALID_DISPLAY;
 
 import android.annotation.NonNull;
+import android.annotation.Nullable;
 import android.annotation.TestApi;
 import android.app.ActivityManager.StackInfo;
 import android.content.ComponentName;
@@ -324,16 +325,17 @@
      * this method can be called.
      *
      * @param pendingIntent Intent used to launch an activity.
+     * @param fillInIntent Additional Intent data, see {@link Intent#fillIn Intent.fillIn()}.
      * @param options options for the activity
      *
      * @see StateCallback
      * @see #startActivity(Intent)
      */
-    public void startActivity(@NonNull PendingIntent pendingIntent,
+    public void startActivity(@NonNull PendingIntent pendingIntent, @Nullable Intent fillInIntent,
             @NonNull ActivityOptions options) {
         options.setLaunchDisplayId(mVirtualDisplay.getDisplay().getDisplayId());
         try {
-            pendingIntent.send(null /* context */, 0 /* code */, null /* intent */,
+            pendingIntent.send(getContext(), 0 /* code */, fillInIntent,
                     null /* onFinished */, null /* handler */, null /* requiredPermission */,
                     options.toBundle());
         } catch (PendingIntent.CanceledException e) {
diff --git a/core/java/android/app/ApplicationPackageManager.java b/core/java/android/app/ApplicationPackageManager.java
index a201307..86bf20a 100644
--- a/core/java/android/app/ApplicationPackageManager.java
+++ b/core/java/android/app/ApplicationPackageManager.java
@@ -3169,6 +3169,15 @@
     }
 
     @Override
+    public String getSetupWizardPackageName() {
+        try {
+            return mPM.getSetupWizardPackageName();
+        } catch (RemoteException e) {
+            throw e.rethrowAsRuntimeException();
+        }
+    }
+
+    @Override
     public String getIncidentReportApproverPackageName() {
         try {
             return mPM.getIncidentReportApproverPackageName();
diff --git a/core/java/android/app/ContextImpl.java b/core/java/android/app/ContextImpl.java
index ef23d5e..39fab63 100644
--- a/core/java/android/app/ContextImpl.java
+++ b/core/java/android/app/ContextImpl.java
@@ -741,12 +741,21 @@
     public File getCodeCacheDir() {
         synchronized (mSync) {
             if (mCodeCacheDir == null) {
-                mCodeCacheDir = new File(getDataDir(), "code_cache");
+                mCodeCacheDir = getCodeCacheDirBeforeBind(getDataDir());
             }
             return ensurePrivateCacheDirExists(mCodeCacheDir, XATTR_INODE_CODE_CACHE);
         }
     }
 
+    /**
+     * Helper for getting code-cache dir potentially before application bind.
+     *
+     * @hide
+     */
+    static File getCodeCacheDirBeforeBind(File dataDir) {
+        return new File(dataDir, "code_cache");
+    }
+
     @Override
     public File getExternalCacheDir() {
         // Operates on primary external storage
@@ -2203,6 +2212,15 @@
     }
 
     @Override
+    public Context createContextAsUser(UserHandle user) {
+        try {
+            return createPackageContextAsUser(getPackageName(), mFlags, user);
+        } catch (NameNotFoundException e) {
+            throw new IllegalStateException("Own package not found: package=" + getPackageName());
+        }
+    }
+
+    @Override
     public Context createContextForSplit(String splitName) throws NameNotFoundException {
         if (!mPackageInfo.getApplicationInfo().requestsIsolatedSplitLoading()) {
             // All Splits are always loaded.
diff --git a/core/java/android/app/IActivityTaskManager.aidl b/core/java/android/app/IActivityTaskManager.aidl
index dda3bb5..f591441 100644
--- a/core/java/android/app/IActivityTaskManager.aidl
+++ b/core/java/android/app/IActivityTaskManager.aidl
@@ -215,7 +215,6 @@
 
     void releaseSomeActivities(in IApplicationThread app);
     Bitmap getTaskDescriptionIcon(in String filename, int userId);
-    void startInPlaceAnimationOnFrontMostApplication(in Bundle opts);
     void registerTaskStackListener(in ITaskStackListener listener);
     void unregisterTaskStackListener(in ITaskStackListener listener);
     void setTaskResizeable(int taskId, int resizeableMode);
diff --git a/core/java/android/app/IApplicationThread.aidl b/core/java/android/app/IApplicationThread.aidl
index cfa065b..51a64ff 100644
--- a/core/java/android/app/IApplicationThread.aidl
+++ b/core/java/android/app/IApplicationThread.aidl
@@ -137,6 +137,7 @@
             IVoiceInteractor voiceInteractor);
     void handleTrustStorageUpdate();
     void attachAgent(String path);
+    void attachStartupAgents(String dataDir);
     void scheduleApplicationInfoChanged(in ApplicationInfo ai);
     void setNetworkBlockSeq(long procStateSeq);
     void scheduleTransaction(in ClientTransaction transaction);
diff --git a/core/java/android/app/ITaskStackListener.aidl b/core/java/android/app/ITaskStackListener.aidl
index 750020e..0ba1989 100644
--- a/core/java/android/app/ITaskStackListener.aidl
+++ b/core/java/android/app/ITaskStackListener.aidl
@@ -197,4 +197,11 @@
      * Called when any additions or deletions to the recent tasks list have been made.
      */
     void onRecentTaskListUpdated();
+
+    /**
+     * Called when Recent Tasks list is frozen or unfrozen.
+     *
+     * @param frozen if true, Recents Tasks list is currently frozen, false otherwise
+     */
+    void onRecentTaskListFrozenChanged(boolean frozen);
 }
diff --git a/core/java/android/app/KeyguardManager.java b/core/java/android/app/KeyguardManager.java
index 9b667a1..b1565ab 100644
--- a/core/java/android/app/KeyguardManager.java
+++ b/core/java/android/app/KeyguardManager.java
@@ -87,12 +87,6 @@
             "android.app.action.CONFIRM_FRP_CREDENTIAL";
 
     /**
-     * @hide
-     */
-    public static final String EXTRA_BIOMETRIC_PROMPT_BUNDLE =
-            "android.app.extra.BIOMETRIC_PROMPT_BUNDLE";
-
-    /**
      * A CharSequence dialog title to show to the user when used with a
      * {@link #ACTION_CONFIRM_DEVICE_CREDENTIAL}.
      * @hide
diff --git a/core/java/android/app/ResourcesManager.java b/core/java/android/app/ResourcesManager.java
index 40cb29f..cb9ebac 100644
--- a/core/java/android/app/ResourcesManager.java
+++ b/core/java/android/app/ResourcesManager.java
@@ -20,6 +20,7 @@
 
 import android.annotation.NonNull;
 import android.annotation.Nullable;
+import android.annotation.TestApi;
 import android.annotation.UnsupportedAppUsage;
 import android.content.pm.ActivityInfo;
 import android.content.pm.ApplicationInfo;
@@ -191,6 +192,17 @@
                 }
             }
             Log.i(TAG, "Invalidated " + count + " asset managers that referenced " + path);
+
+            for (int i = mCachedApkAssets.size() - 1; i >= 0; i--) {
+                final ApkKey key = mCachedApkAssets.keyAt(i);
+                if (key.path.equals(path)) {
+                    WeakReference<ApkAssets> apkAssetsRef = mCachedApkAssets.remove(key);
+                    if (apkAssetsRef != null && apkAssetsRef.get() != null) {
+                        apkAssetsRef.get().close();
+                    }
+                    mCachedApkAssets.remove(key);
+                }
+            }
         }
     }
 
@@ -1000,6 +1012,14 @@
         }
     }
 
+    @TestApi
+    public final boolean applyConfigurationToResources(@NonNull Configuration config,
+            @Nullable CompatibilityInfo compat) {
+        synchronized(this) {
+            return applyConfigurationToResourcesLocked(config, compat);
+        }
+    }
+
     public final boolean applyConfigurationToResourcesLocked(@NonNull Configuration config,
                                                              @Nullable CompatibilityInfo compat) {
         try {
diff --git a/core/java/android/app/SystemServiceRegistry.java b/core/java/android/app/SystemServiceRegistry.java
index 0499337..e81dc1c 100644
--- a/core/java/android/app/SystemServiceRegistry.java
+++ b/core/java/android/app/SystemServiceRegistry.java
@@ -1343,13 +1343,13 @@
      * @hide
      */
     public static <T> void registerCachedService(String serviceName, Class<T> serviceWrapperClass,
-            BiFunction<ContextImpl, IBinder, T> serviceFetcher) {
+            BiFunction<Context, IBinder, T> serviceFetcher) {
         registerService(serviceName, serviceWrapperClass,
                 new CachedServiceFetcher<T>() {
                     @Override
                     public T createService(ContextImpl ctx) throws ServiceNotFoundException {
                         IBinder b = ServiceManager.getServiceOrThrow(serviceName);
-                        return serviceFetcher.apply(ctx, b);
+                        return serviceFetcher.apply(ctx.getOuterContext(), b);
                     }});
     }
 
diff --git a/core/java/android/app/TaskStackListener.java b/core/java/android/app/TaskStackListener.java
index 46045fa..f21aaf3 100644
--- a/core/java/android/app/TaskStackListener.java
+++ b/core/java/android/app/TaskStackListener.java
@@ -190,4 +190,8 @@
     @Override
     public void onRecentTaskListUpdated() throws RemoteException {
     }
+
+    @Override
+    public void onRecentTaskListFrozenChanged(boolean frozen) {
+    }
 }
diff --git a/core/java/android/app/UiAutomation.java b/core/java/android/app/UiAutomation.java
index fd93450..13d566c 100644
--- a/core/java/android/app/UiAutomation.java
+++ b/core/java/android/app/UiAutomation.java
@@ -42,6 +42,7 @@
 import android.os.SystemClock;
 import android.os.UserHandle;
 import android.util.Log;
+import android.util.SparseArray;
 import android.view.Display;
 import android.view.InputEvent;
 import android.view.KeyEvent;
@@ -535,7 +536,7 @@
     }
 
     /**
-     * Gets the windows on the screen. This method returns only the windows
+     * Gets the windows on the screen of the default display. This method returns only the windows
      * that a sighted user can interact with, as opposed to all windows.
      * For example, if there is a modal dialog shown and the user cannot touch
      * anything behind it, then only the modal window will be reported
@@ -562,6 +563,35 @@
     }
 
     /**
+     * Gets the windows on the screen of all displays. This method returns only the windows
+     * that a sighted user can interact with, as opposed to all windows.
+     * For example, if there is a modal dialog shown and the user cannot touch
+     * anything behind it, then only the modal window will be reported
+     * (assuming it is the top one). For convenience the returned windows
+     * are ordered in a descending layer order, which is the windows that
+     * are higher in the Z-order are reported first.
+     * <p>
+     * <strong>Note:</strong> In order to access the windows you have to opt-in
+     * to retrieve the interactive windows by setting the
+     * {@link AccessibilityServiceInfo#FLAG_RETRIEVE_INTERACTIVE_WINDOWS} flag.
+     * </p>
+     *
+     * @return The windows of all displays if there are windows and the service is can retrieve
+     *         them, otherwise an empty list. The key of SparseArray is display ID.
+     */
+    @NonNull
+    public SparseArray<List<AccessibilityWindowInfo>> getWindowsOnAllDisplays() {
+        final int connectionId;
+        synchronized (mLock) {
+            throwIfNotConnectedLocked();
+            connectionId = mConnectionId;
+        }
+        // Calling out without a lock held.
+        return AccessibilityInteractionClient.getInstance()
+                .getWindowsOnAllDisplays(connectionId);
+    }
+
+    /**
      * Gets the root {@link AccessibilityNodeInfo} in the active window.
      *
      * @return The root info.
diff --git a/core/java/android/app/admin/DelegatedAdminReceiver.java b/core/java/android/app/admin/DelegatedAdminReceiver.java
index f66de8d..25b8eab 100644
--- a/core/java/android/app/admin/DelegatedAdminReceiver.java
+++ b/core/java/android/app/admin/DelegatedAdminReceiver.java
@@ -63,6 +63,10 @@
      * Allows this receiver to select the alias for a private key and certificate pair for
      * authentication.  If this method returns null, the default {@link android.app.Activity} will
      * be shown that lets the user pick a private key and certificate pair.
+     * If this method returns {@link KeyChain#KEY_ALIAS_SELECTION_DENIED},
+     * the default {@link android.app.Activity} will not be shown and the user will not be allowed
+     * to pick anything. And the app, that called {@link KeyChain#choosePrivateKeyAlias}, will
+     * receive {@code null} back.
      *
      * <p> This callback is only applicable if the delegated app has
      * {@link DevicePolicyManager#DELEGATION_CERT_SELECTION} capability. Additionally, it must
diff --git a/core/java/android/app/admin/DeviceAdminReceiver.java b/core/java/android/app/admin/DeviceAdminReceiver.java
index 0c500da..d175a66 100644
--- a/core/java/android/app/admin/DeviceAdminReceiver.java
+++ b/core/java/android/app/admin/DeviceAdminReceiver.java
@@ -791,6 +791,10 @@
      * Allows this receiver to select the alias for a private key and certificate pair for
      * authentication. If this method returns null, the default {@link android.app.Activity} will be
      * shown that lets the user pick a private key and certificate pair.
+     * If this method returns {@link KeyChain#KEY_ALIAS_SELECTION_DENIED},
+     * the default {@link android.app.Activity} will not be shown and the user will not be allowed
+     * to pick anything. And the app, that called {@link KeyChain#choosePrivateKeyAlias}, will
+     * receive {@code null} back.
      *
      * @param context The running context as per {@link #onReceive}.
      * @param intent The received intent as per {@link #onReceive}.
diff --git a/core/java/android/app/admin/DevicePolicyManagerInternal.java b/core/java/android/app/admin/DevicePolicyManagerInternal.java
index b873be3..713126e 100644
--- a/core/java/android/app/admin/DevicePolicyManagerInternal.java
+++ b/core/java/android/app/admin/DevicePolicyManagerInternal.java
@@ -24,6 +24,10 @@
 /**
  * Device policy manager local system service interface.
  *
+ * Maintenance note: if you need to expose information from DPMS to lower level services such as
+ * PM/UM/AM/etc, then exposing it from DevicePolicyManagerInternal is not safe because it may cause
+ * lock order inversion. Consider using {@link DevicePolicyCache} instead.
+ *
  * @hide Only for use within the system server.
  */
 public abstract class DevicePolicyManagerInternal {
@@ -81,6 +85,16 @@
     public abstract boolean isActiveAdminWithPolicy(int uid, int reqPolicy);
 
     /**
+     * Checks if an app with given uid is the active supervision admin.
+     *
+     * <p>This takes the DPMS lock. DO NOT call from PM/UM/AM with their lock held.
+     *
+     * @param uid App uid.
+     * @return true if the uid is the active supervision app.
+     */
+    public abstract boolean isActiveSupervisionApp(int uid);
+
+    /**
      * Creates an intent to show the admin support dialog to say that an action is disallowed by
      * the device/profile owner.
      *
diff --git a/core/java/android/app/role/IRoleManager.aidl b/core/java/android/app/role/IRoleManager.aidl
index d8cea28..6d790b3 100644
--- a/core/java/android/app/role/IRoleManager.aidl
+++ b/core/java/android/app/role/IRoleManager.aidl
@@ -19,7 +19,6 @@
 import android.app.role.IOnRoleHoldersChangedListener;
 import android.os.Bundle;
 import android.os.RemoteCallback;
-import android.telephony.IFinancialSmsCallback;
 
 /**
  * @hide
@@ -55,9 +54,4 @@
     List<String> getHeldRolesFromController(in String packageName);
 
     String getDefaultSmsPackage(int userId);
-
-    /**
-     * Get filtered SMS messages for financial app.
-     */
-    void getSmsMessagesForFinancialApp(in String callingPkg, in Bundle params, in IFinancialSmsCallback callback);
 }
diff --git a/core/java/android/app/usage/AppStandbyInfo.java b/core/java/android/app/usage/AppStandbyInfo.java
index ebdbf83..c283702 100644
--- a/core/java/android/app/usage/AppStandbyInfo.java
+++ b/core/java/android/app/usage/AppStandbyInfo.java
@@ -22,6 +22,10 @@
 /**
  * A pair of {package, bucket} to denote the app standby bucket for a given package.
  * Used as a vehicle of data across the binder IPC.
+ *
+ * Note we're not moving this class to the jobscheduler apex, because it's consumed by
+ * UsageStatsManager, which is not updatable anyway, so making this updatable isn't really
+ * beneficial.
  * @hide
  */
 public final class AppStandbyInfo implements Parcelable {
diff --git a/core/java/android/app/usage/UsageStatsManager.java b/core/java/android/app/usage/UsageStatsManager.java
index 656f474..1f13a1e 100644
--- a/core/java/android/app/usage/UsageStatsManager.java
+++ b/core/java/android/app/usage/UsageStatsManager.java
@@ -801,8 +801,8 @@
      *                       {@link #EXTRA_TIME_USED}. Cannot be {@code null} unless the observer is
      *                       being registered with a {@code timeUsed} equal to or greater than
      *                       {@code timeLimit}.
-     * @throws SecurityException if the caller doesn't have both SUSPEND_APPS and OBSERVE_APP_USAGE
-     *                           permissions.
+     * @throws SecurityException if the caller is neither the active supervision app nor does it
+     *                           have both SUSPEND_APPS and OBSERVE_APP_USAGE permissions.
      * @hide
      */
     @SystemApi
@@ -827,8 +827,8 @@
      * an observer that was already unregistered or never registered will have no effect.
      *
      * @param observerId The id of the observer that was previously registered.
-     * @throws SecurityException if the caller doesn't have both SUSPEND_APPS and OBSERVE_APP_USAGE
-     *                           permissions.
+     * @throws SecurityException if the caller is neither the active supervision app nor does it
+     *                         have both SUSPEND_APPS and OBSERVE_APP_USAGE permissions.
      * @hide
      */
     @SystemApi
diff --git a/core/java/android/content/ContentResolver.java b/core/java/android/content/ContentResolver.java
index 1f48393..7c279fe 100644
--- a/core/java/android/content/ContentResolver.java
+++ b/core/java/android/content/ContentResolver.java
@@ -265,6 +265,7 @@
      * @see #QUERY_ARG_SORT_COLUMNS
      * @see #QUERY_ARG_SORT_DIRECTION
      * @see #QUERY_ARG_SORT_COLLATION
+     * @see #QUERY_ARG_SORT_LOCALE
      */
     public static final String QUERY_ARG_SQL_SELECTION = "android:query-arg-sql-selection";
 
@@ -282,6 +283,7 @@
      * @see #QUERY_ARG_SORT_COLUMNS
      * @see #QUERY_ARG_SORT_DIRECTION
      * @see #QUERY_ARG_SORT_COLLATION
+     * @see #QUERY_ARG_SORT_LOCALE
      */
     public static final String QUERY_ARG_SQL_SELECTION_ARGS =
             "android:query-arg-sql-selection-args";
@@ -297,6 +299,7 @@
      * @see #QUERY_ARG_SORT_COLUMNS
      * @see #QUERY_ARG_SORT_DIRECTION
      * @see #QUERY_ARG_SORT_COLLATION
+     * @see #QUERY_ARG_SORT_LOCALE
      */
     public static final String QUERY_ARG_SQL_SORT_ORDER = "android:query-arg-sql-sort-order";
 
@@ -351,20 +354,22 @@
 
     /**
      * Allows client to specify a hint to the provider declaring which collation
-     * to use when sorting text values.
-     *
-     * <p>Providers may support custom collators. When specifying a custom collator
+     * to use when sorting values.
+     * <p>
+     * Providers may support custom collators. When specifying a custom collator
      * the value is determined by the Provider.
-     *
-     * <li>{@link ContentProvider} implementations: When preparing data in
-     * {@link ContentProvider#query(Uri, String[], Bundle, CancellationSignal)}, if sort collation
-     * is reflected in the returned Cursor, it is  strongly recommended that
-     * {@link #QUERY_ARG_SORT_COLLATION} then be included in the array of honored arguments
-     * reflected in {@link Cursor} extras {@link Bundle} under {@link #EXTRA_HONORED_ARGS}.
-     *
-     * <li>When querying a provider, where no QUERY_ARG_SQL* otherwise exists in the
-     * arguments {@link Bundle}, the Content framework will attempt to synthesize
-     * a QUERY_ARG_SQL* argument using the corresponding QUERY_ARG_SORT* values.
+     * <p>
+     * {@link ContentProvider} implementations: When preparing data in
+     * {@link ContentProvider#query(Uri, String[], Bundle, CancellationSignal)},
+     * if sort collation is reflected in the returned Cursor, it is strongly
+     * recommended that {@link #QUERY_ARG_SORT_COLLATION} then be included in
+     * the array of honored arguments reflected in {@link Cursor} extras
+     * {@link Bundle} under {@link #EXTRA_HONORED_ARGS}.
+     * <p>
+     * When querying a provider, where no QUERY_ARG_SQL* otherwise exists in the
+     * arguments {@link Bundle}, the Content framework will attempt to
+     * synthesize a QUERY_ARG_SQL* argument using the corresponding
+     * QUERY_ARG_SORT* values.
      *
      * @see java.text.Collator#PRIMARY
      * @see java.text.Collator#SECONDARY
@@ -374,6 +379,28 @@
     public static final String QUERY_ARG_SORT_COLLATION = "android:query-arg-sort-collation";
 
     /**
+     * Allows client to specify a hint to the provider declaring which locale to
+     * use when sorting values.
+     * <p>
+     * The value is defined as a RFC 3066 locale ID followed by an optional
+     * keyword list, which is the locale format used to configure ICU through
+     * classes like {@link android.icu.util.ULocale}. This supports requesting
+     * advanced sorting options, such as {@code de@collation=phonebook},
+     * {@code zh@collation=pinyin}, etc.
+     * <p>
+     * {@link ContentProvider} implementations: When preparing data in
+     * {@link ContentProvider#query(Uri, String[], Bundle, CancellationSignal)},
+     * if sort locale is reflected in the returned Cursor, it is strongly
+     * recommended that {@link #QUERY_ARG_SORT_LOCALE} then be included in the
+     * array of honored arguments reflected in {@link Cursor} extras
+     * {@link Bundle} under {@link #EXTRA_HONORED_ARGS}.
+     *
+     * @see java.util.Locale#Locale(String)
+     * @see android.icu.util.ULocale#ULocale(String)
+     */
+    public static final String QUERY_ARG_SORT_LOCALE = "android:query-arg-sort-locale";
+
+    /**
      * Allows provider to report back to client which query keys are honored in a Cursor.
      *
      * <p>Key identifying a {@code String[]} containing all QUERY_ARG_SORT* arguments
@@ -386,6 +413,7 @@
      * @see #QUERY_ARG_SORT_COLUMNS
      * @see #QUERY_ARG_SORT_DIRECTION
      * @see #QUERY_ARG_SORT_COLLATION
+     * @see #QUERY_ARG_SORT_LOCALE
      */
     public static final String EXTRA_HONORED_ARGS = "android.content.extra.HONORED_ARGS";
 
diff --git a/core/java/android/content/Context.java b/core/java/android/content/Context.java
index 802c1a0a..227684b 100644
--- a/core/java/android/content/Context.java
+++ b/core/java/android/content/Context.java
@@ -1559,7 +1559,14 @@
      * @see Environment#getExternalStorageState(File)
      * @see Environment#isExternalStorageEmulated(File)
      * @see Environment#isExternalStorageRemovable(File)
+     * @deprecated These directories still exist and are scanned, but developers
+     *             are encouraged to migrate to inserting content into a
+     *             {@link MediaStore} collection directly, as any app can
+     *             contribute new media to {@link MediaStore} with no
+     *             permissions required, starting in
+     *             {@link android.os.Build.VERSION_CODES#Q}.
      */
+    @Deprecated
     public abstract File[] getExternalMediaDirs();
 
     /**
@@ -3301,7 +3308,7 @@
      *  <dt> {@link #VIBRATOR_SERVICE} ("vibrator")
      *  <dd> A {@link android.os.Vibrator} for interacting with the vibrator
      *  hardware.
-     *  <dt> {@link #CONNECTIVITY_SERVICE} ("connection")
+     *  <dt> {@link #CONNECTIVITY_SERVICE} ("connectivity")
      *  <dd> A {@link android.net.ConnectivityManager ConnectivityManager} for
      *  handling management of network connections.
      *  <dt> {@link #IPSEC_SERVICE} ("ipsec")
@@ -5217,8 +5224,9 @@
      */
     @SystemApi
     @TestApi
+    @NonNull
     public Context createPackageContextAsUser(
-            String packageName, @CreatePackageOptions int flags, UserHandle user)
+            @NonNull String packageName, @CreatePackageOptions int flags, @NonNull UserHandle user)
             throws PackageManager.NameNotFoundException {
         if (Build.IS_ENG) {
             throw new IllegalStateException("createPackageContextAsUser not overridden!");
@@ -5227,6 +5235,23 @@
     }
 
     /**
+     * Similar to {@link #createPackageContext(String, int)}, but for the own package with a
+     * different {@link UserHandle}. For example, {@link #getContentResolver()}
+     * will open any {@link Uri} as the given user.
+     *
+     * @hide
+     */
+    @SystemApi
+    @TestApi
+    @NonNull
+    public Context createContextAsUser(@NonNull UserHandle user) {
+        if (Build.IS_ENG) {
+            throw new IllegalStateException("createContextAsUser not overridden!");
+        }
+        return this;
+    }
+
+    /**
      * Creates a context given an {@link android.content.pm.ApplicationInfo}.
      *
      * @hide
diff --git a/core/java/android/content/ContextWrapper.java b/core/java/android/content/ContextWrapper.java
index 0859f97..f7cd51e 100644
--- a/core/java/android/content/ContextWrapper.java
+++ b/core/java/android/content/ContextWrapper.java
@@ -885,6 +885,12 @@
 
     /** @hide */
     @Override
+    public Context createContextAsUser(UserHandle user) {
+        return mBase.createContextAsUser(user);
+    }
+
+    /** @hide */
+    @Override
     @UnsupportedAppUsage
     public Context createApplicationContext(ApplicationInfo application,
             int flags) throws PackageManager.NameNotFoundException {
diff --git a/core/java/android/content/Intent.java b/core/java/android/content/Intent.java
index 39ddc82..efb1c6a 100644
--- a/core/java/android/content/Intent.java
+++ b/core/java/android/content/Intent.java
@@ -4654,6 +4654,59 @@
      */
     @SdkConstant(SdkConstantType.INTENT_CATEGORY)
     public static final String CATEGORY_VR_HOME = "android.intent.category.VR_HOME";
+
+    /**
+     * The accessibility shortcut is a global gesture for users with disabilities to trigger an
+     * important for them accessibility feature to help developers determine whether they want to
+     * make their activity a shortcut target.
+     * <p>
+     * An activity of interest to users with accessibility needs may request to be the target of
+     * the accessibility shortcut. It handles intent {@link #ACTION_MAIN} with this category,
+     * which will be dispatched by the system when the user activates the shortcut when it is
+     * configured to point at this target.
+     * </p>
+     * <p>
+     * An activity declared itself to be a target of the shortcut in AndroidManifest.xml. It must
+     * also do two things:
+     * <ul>
+     *     <ol>
+     *         Specify that it handles the <code>android.intent.action.MAIN</code>
+     *         {@link android.content.Intent}
+     *         with category <code>android.intent.category.ACCESSIBILITY_SHORTCUT_TARGET</code>.
+     *     </ol>
+     *     <ol>
+     *         Provide a meta-data entry <code>android.accessibilityshortcut.target</code> in the
+     *         manifest when declaring the activity.
+     *     </ol>
+     * </ul>
+     * If either of these items is missing, the system will ignore the accessibility shortcut
+     * target. Following is an example declaration:
+     * </p>
+     * <pre>
+     * &lt;activity android:name=".MainActivity"
+     * . . .
+     *   &lt;intent-filter&gt;
+     *       &lt;action android:name="android.intent.action.MAIN" /&gt;
+     *       &lt;category android:name="android.intent.category.ACCESSIBILITY_SHORTCUT_TARGET" /&gt;
+     *   &lt;/intent-filter&gt;
+     *   &lt;meta-data android:name="android.accessibilityshortcut.target"
+     *                   android:resource="@xml/accessibilityshortcut" /&gt;
+     * &lt;/activity&gt;
+     * </pre>
+     * <p> This is a sample XML file configuring a accessibility shortcut target: </p>
+     * <pre>
+     * &lt;accessibility-shortcut-target
+     *     android:description="@string/shortcut_target_description"
+     *     android:summary="@string/shortcut_target_summary" /&gt;
+     * </pre>
+     * <p>
+     * Both description and summary are necessary. The system will ignore the accessibility
+     * shortcut target if they are missing.
+     * </p>
+     */
+    @SdkConstant(SdkConstantType.INTENT_CATEGORY)
+    public static final String CATEGORY_ACCESSIBILITY_SHORTCUT_TARGET =
+            "android.intent.category.ACCESSIBILITY_SHORTCUT_TARGET";
     // ---------------------------------------------------------------------
     // ---------------------------------------------------------------------
     // Application launch intent categories (see addCategory()).
diff --git a/core/java/android/content/PermissionChecker.java b/core/java/android/content/PermissionChecker.java
index e24512a..c3daad1 100644
--- a/core/java/android/content/PermissionChecker.java
+++ b/core/java/android/content/PermissionChecker.java
@@ -16,8 +16,6 @@
 
 package android.content;
 
-import static android.app.AppOpsManager.strOpToOp;
-
 import android.annotation.IntDef;
 import android.annotation.NonNull;
 import android.annotation.Nullable;
@@ -52,6 +50,19 @@
  * permission model for which the user had disabled the "permission"
  * which is achieved by disallowing the corresponding app op.
  * </p>
+ * <p>
+ * This class has two types of methods and you should be careful which
+ * type to call based on whether permission protected data is being
+ * passed to the app or you are just checking whether the app holds a
+ * permission. The reason is that a permission check requires checking
+ * the runtime permission and if it is granted checking the corresponding
+ * app op as for apps not supporting the runtime mode we never revoke
+ * permissions but disable app ops. Since there are two types of app op
+ * checks, one that does not leave a record an action was performed and
+ * another the does, one needs to call the preflight flavor of the checks
+ * named xxxForPreflight only if no private data is being delivered but
+ * a permission check is what is needed and the xxxForDataDelivery where
+ * the permission check is right before private data delivery.
  *
  * @hide
  */
@@ -65,6 +76,9 @@
     /** Permission result: The permission is denied because the app op is not allowed. */
     public static final int PERMISSION_DENIED_APP_OP =  PackageManager.PERMISSION_DENIED  - 1;
 
+    /** Constant when the PID for which we check permissions is unknown. */
+    public static final int PID_UNKNOWN = -1;
+
     /** @hide */
     @IntDef({PERMISSION_GRANTED,
             PERMISSION_DENIED,
@@ -77,33 +91,297 @@
     }
 
     /**
-     * @deprecated Use {@link #checkPermission(Context, String, int, int, String, String)} instead
+     * Checks whether a given package in a UID and PID has a given permission
+     * and whether the app op that corresponds to this permission is allowed.
+     *
+     * <strong>NOTE:</strong> Use this method only for permission checks at the
+     * point where you will deliver the permission protected data to clients.
+     *
+     * <p>For example, if an app registers a location listener it should have the location
+     * permission but no data is actually sent to the app at the moment of registration
+     * and you should use {@link #checkPermissionForPreflight(Context, String, int, int, String)}
+     * to determine if the app has or may have location permission (if app has only foreground
+     * location the grant state depends on the app's fg/gb state) and this check will not
+     * leave a trace that permission protected data was delivered. When you are about to
+     * deliver the location data to a registered listener you should use this method which
+     * will evaluate the permission access based on the current fg/bg state of the app and
+     * leave a record that the data was accessed.
+     *
+     * @param context Context for accessing resources.
+     * @param permission The permission to check.
+     * @param pid The process id for which to check. Use {@link #PID_UNKNOWN} if the PID
+     *    is not known.
+     * @param uid The uid for which to check.
+     * @param packageName The package name for which to check. If null the
+     *     the first package for the calling UID will be used.
+     * @return The permission check result which is either {@link #PERMISSION_GRANTED}
+     *     or {@link #PERMISSION_DENIED} or {@link #PERMISSION_DENIED_APP_OP}.
+     * @param message A message describing the reason the permission was checked
+     *
+     * @see #checkPermissionForPreflight(Context, String, int, int, String)
      */
-    @Deprecated
     @PermissionResult
-    public static int checkPermission(@NonNull Context context, @NonNull String permission,
-            int pid, int uid, @Nullable String packageName) {
-        return checkPermission(context, permission, pid, uid, packageName, null);
+    public static int checkPermissionForDataDelivery(@NonNull Context context,
+            @NonNull String permission, int pid, int uid, @Nullable String packageName,
+            @Nullable String message) {
+        return checkPermissionCommon(context, permission, pid, uid, packageName, message,
+                true /*forDataDelivery*/);
     }
 
     /**
      * Checks whether a given package in a UID and PID has a given permission
      * and whether the app op that corresponds to this permission is allowed.
      *
+     * <strong>NOTE:</strong> Use this method only for permission checks at the
+     * preflight point where you will not deliver the permission protected data
+     * to clients but schedule permission data delivery, apps register listeners,
+     * etc.
+     *
+     * <p>For example, if an app registers a location listener it should have the location
+     * permission but no data is actually sent to the app at the moment of registration
+     * and you should use this method to determine if the app has or may have location
+     * permission (if app has only foreground location the grant state depends on the app's
+     * fg/gb state) and this check will not leave a trace that permission protected data
+     * was delivered. When you are about to deliver the location data to a registered
+     * listener you should use {@link #checkPermissionForDataDelivery(Context, String,
+     * int, int, String, String)} which will evaluate the permission access based on the current
+     * fg/bg state of the app and leave a record that the data was accessed.
+     *
      * @param context Context for accessing resources.
      * @param permission The permission to check.
      * @param pid The process id for which to check.
      * @param uid The uid for which to check.
      * @param packageName The package name for which to check. If null the
      *     the first package for the calling UID will be used.
-     * @param message A message describing the reason the permission was checked
-     *
      * @return The permission check result which is either {@link #PERMISSION_GRANTED}
      *     or {@link #PERMISSION_DENIED} or {@link #PERMISSION_DENIED_APP_OP}.
+     *
+     * @see #checkPermissionForDataDelivery(Context, String, int, int, String, String)
      */
     @PermissionResult
-    public static int checkPermission(@NonNull Context context, @NonNull String permission,
-            int pid, int uid, @Nullable String packageName, @Nullable String message) {
+    public static int checkPermissionForPreflight(@NonNull Context context,
+            @NonNull String permission, int pid, int uid, @Nullable String packageName) {
+        return checkPermissionCommon(context, permission, pid, uid, packageName, null /*message*/,
+                false /*forDataDelivery*/);
+    }
+
+    /**
+     * Checks whether your app has a given permission and whether the app op
+     * that corresponds to this permission is allowed.
+     *
+     * <strong>NOTE:</strong> Use this method only for permission checks at the
+     * point where you will deliver the permission protected data to clients.
+     *
+     * <p>For example, if an app registers a location listener it should have the location
+     * permission but no data is actually sent to the app at the moment of registration
+     * and you should use {@link #checkSelfPermissionForPreflight(Context, String)}
+     * to determine if the app has or may have location permission (if app has only foreground
+     * location the grant state depends on the app's fg/gb state) and this check will not
+     * leave a trace that permission protected data was delivered. When you are about to
+     * deliver the location data to a registered listener you should use this method
+     * which will evaluate the permission access based on the current fg/bg state of the
+     * app and leave a record that the data was accessed.
+     *
+     * <p>This API assumes the the {@link Binder#getCallingUid()} is the same as
+     * {@link Process#myUid()}.
+     *
+     * @param context Context for accessing resources.
+     * @param permission The permission to check.
+     * @return The permission check result which is either {@link #PERMISSION_GRANTED}
+     *     or {@link #PERMISSION_DENIED} or {@link #PERMISSION_DENIED_APP_OP}.
+     * @param message A message describing the reason the permission was checked
+     *
+     * @see #checkSelfPermissionForPreflight(Context, String)
+     */
+    @PermissionResult
+    public static int checkSelfPermissionForDataDelivery(@NonNull Context context,
+            @NonNull String permission, @Nullable String message) {
+        return checkPermissionForDataDelivery(context, permission, Process.myPid(),
+                Process.myUid(), context.getPackageName(), message);
+    }
+
+    /**
+     * Checks whether your app has a given permission and whether the app op
+     * that corresponds to this permission is allowed.
+     *
+     * <strong>NOTE:</strong> Use this method only for permission checks at the
+     * preflight point where you will not deliver the permission protected data
+     * to clients but schedule permission data delivery, apps register listeners,
+     * etc.
+     *
+     * <p>For example, if an app registers a location listener it should have the location
+     * permission but no data is actually sent to the app at the moment of registration
+     * and you should use this method to determine if the app has or may have location
+     * permission (if app has only foreground location the grant state depends on the
+     * app's fg/gb state) and this check will not leave a trace that permission protected
+     * data was delivered. When you are about to deliver the location data to a registered
+     * listener you should use this method which will evaluate the permission access based
+     * on the current fg/bg state of the app and leave a record that the data was accessed.
+     *
+     * <p>This API assumes the the {@link Binder#getCallingUid()} is the same as
+     * {@link Process#myUid()}.
+     *
+     * @param context Context for accessing resources.
+     * @param permission The permission to check.
+     * @return The permission check result which is either {@link #PERMISSION_GRANTED}
+     *     or {@link #PERMISSION_DENIED} or {@link #PERMISSION_DENIED_APP_OP}.
+     *
+     * @see #checkSelfPermissionForDataDelivery(Context, String, String)
+     */
+    @PermissionResult
+    public static int checkSelfPermissionForPreflight(@NonNull Context context,
+            @NonNull String permission) {
+        return checkPermissionForPreflight(context, permission, Process.myPid(),
+                Process.myUid(), context.getPackageName());
+    }
+
+    /**
+     * Checks whether the IPC you are handling has a given permission and whether
+     * the app op that corresponds to this permission is allowed.
+     *
+     * <strong>NOTE:</strong> Use this method only for permission checks at the
+     * point where you will deliver the permission protected data to clients.
+     *
+     * <p>For example, if an app registers a location listener it should have the location
+     * permission but no data is actually sent to the app at the moment of registration
+     * and you should use {@link #checkCallingPermissionForPreflight(Context, String, String)}
+     * to determine if the app has or may have location permission (if app has only foreground
+     * location the grant state depends on the app's fg/gb state) and this check will not
+     * leave a trace that permission protected data was delivered. When you are about to
+     * deliver the location data to a registered listener you should use this method which
+     * will evaluate the permission access based on the current fg/bg state of the app and
+     * leave a record that the data was accessed.
+     *
+     * @param context Context for accessing resources.
+     * @param permission The permission to check.
+     * @param packageName The package name making the IPC. If null the
+     *     the first package for the calling UID will be used.
+     * @return The permission check result which is either {@link #PERMISSION_GRANTED}
+     *     or {@link #PERMISSION_DENIED} or {@link #PERMISSION_DENIED_APP_OP}.
+     * @param message A message describing the reason the permission was checked
+     *
+     * @see #checkCallingPermissionForPreflight(Context, String, String)
+     */
+    @PermissionResult
+    public static int checkCallingPermissionForDataDelivery(@NonNull Context context,
+            @NonNull String permission, @Nullable String packageName, @Nullable String message) {
+        if (Binder.getCallingPid() == Process.myPid()) {
+            return PERMISSION_DENIED;
+        }
+        return checkPermissionForDataDelivery(context, permission, Binder.getCallingPid(),
+                Binder.getCallingUid(), packageName, message);
+    }
+
+    /**
+     * Checks whether the IPC you are handling has a given permission and whether
+     * the app op that corresponds to this permission is allowed.
+     *
+     * <strong>NOTE:</strong> Use this method only for permission checks at the
+     * preflight point where you will not deliver the permission protected data
+     * to clients but schedule permission data delivery, apps register listeners,
+     * etc.
+     *
+     * <p>For example, if an app registers a location listener it should have the location
+     * permission but no data is actually sent to the app at the moment of registration
+     * and you should use this method to determine if the app has or may have location
+     * permission (if app has only foreground location the grant state depends on the app's
+     * fg/gb state) and this check will not leave a trace that permission protected data
+     * was delivered. When you are about to deliver the location data to a registered
+     * listener you should use {@link #checkCallingOrSelfPermissionForDataDelivery(Context,
+     * String, String)} which will evaluate the permission access based on the current fg/bg state
+     * of the app and leave a record that the data was accessed.
+     *
+     * @param context Context for accessing resources.
+     * @param permission The permission to check.
+     * @param packageName The package name making the IPC. If null the
+     *     the first package for the calling UID will be used.
+     * @return The permission check result which is either {@link #PERMISSION_GRANTED}
+     *     or {@link #PERMISSION_DENIED} or {@link #PERMISSION_DENIED_APP_OP}.
+     *
+     * @see #checkCallingPermissionForDataDelivery(Context, String, String, String)
+     */
+    @PermissionResult
+    public static int checkCallingPermissionForPreflight(@NonNull Context context,
+            @NonNull String permission, @Nullable String packageName) {
+        if (Binder.getCallingPid() == Process.myPid()) {
+            return PERMISSION_DENIED;
+        }
+        return checkPermissionForPreflight(context, permission, Binder.getCallingPid(),
+                Binder.getCallingUid(), packageName);
+    }
+
+    /**
+     * Checks whether the IPC you are handling or your app has a given permission
+     * and whether the app op that corresponds to this permission is allowed.
+     *
+     * <strong>NOTE:</strong> Use this method only for permission checks at the
+     * point where you will deliver the permission protected data to clients.
+     *
+     * <p>For example, if an app registers a location listener it should have the location
+     * permission but no data is actually sent to the app at the moment of registration
+     * and you should use {@link #checkCallingOrSelfPermissionForPreflight(Context, String)}
+     * to determine if the app has or may have location permission (if app has only foreground
+     * location the grant state depends on the app's fg/gb state) and this check will not
+     * leave a trace that permission protected data was delivered. When you are about to
+     * deliver the location data to a registered listener you should use this method which
+     * will evaluate the permission access based on the current fg/bg state of the app and
+     * leave a record that the data was accessed.
+     *
+     * @param context Context for accessing resources.
+     * @param permission The permission to check.
+     * @return The permission check result which is either {@link #PERMISSION_GRANTED}
+     *     or {@link #PERMISSION_DENIED} or {@link #PERMISSION_DENIED_APP_OP}.
+     * @param message A message describing the reason the permission was checked
+     *
+     * @see #checkCallingOrSelfPermissionForPreflight(Context, String)
+     */
+    @PermissionResult
+    public static int checkCallingOrSelfPermissionForDataDelivery(@NonNull Context context,
+            @NonNull String permission, @Nullable String message) {
+        String packageName = (Binder.getCallingPid() == Process.myPid())
+                ? context.getPackageName() : null;
+        return checkPermissionForDataDelivery(context, permission, Binder.getCallingPid(),
+                Binder.getCallingUid(), packageName, message);
+    }
+
+    /**
+     * Checks whether the IPC you are handling or your app has a given permission
+     * and whether the app op that corresponds to this permission is allowed.
+     *
+     * <strong>NOTE:</strong> Use this method only for permission checks at the
+     * preflight point where you will not deliver the permission protected data
+     * to clients but schedule permission data delivery, apps register listeners,
+     * etc.
+     *
+     * <p>For example, if an app registers a location listener it should have the location
+     * permission but no data is actually sent to the app at the moment of registration
+     * and you should use this method to determine if the app has or may have location
+     * permission (if app has only foreground location the grant state depends on the
+     * app's fg/gb state) and this check will not leave a trace that permission protected
+     * data was delivered. When you are about to deliver the location data to a registered
+     * listener you should use {@link #checkCallingOrSelfPermissionForDataDelivery(Context,
+     * String, String)} which will evaluate the permission access based on the current fg/bg state
+     * of the app and leave a record that the data was accessed.
+     *
+     * @param context Context for accessing resources.
+     * @param permission The permission to check.
+     * @return The permission check result which is either {@link #PERMISSION_GRANTED}
+     *     or {@link #PERMISSION_DENIED} or {@link #PERMISSION_DENIED_APP_OP}.
+     *
+     * @see #checkCallingOrSelfPermissionForDataDelivery(Context, String, String)
+     */
+    @PermissionResult
+    public static int checkCallingOrSelfPermissionForPreflight(@NonNull Context context,
+            @NonNull String permission) {
+        String packageName = (Binder.getCallingPid() == Process.myPid())
+                ? context.getPackageName() : null;
+        return checkPermissionForPreflight(context, permission, Binder.getCallingPid(),
+                Binder.getCallingUid(), packageName);
+    }
+
+    private static int checkPermissionCommon(@NonNull Context context, @NonNull String permission,
+            int pid, int uid, @Nullable String packageName, @Nullable String message,
+            boolean forDataDelivery) {
         if (context.checkPermission(permission, pid, uid) == PackageManager.PERMISSION_DENIED) {
             return PERMISSION_DENIED;
         }
@@ -122,93 +400,18 @@
             packageName = packageNames[0];
         }
 
-        if (appOpsManager.noteProxyOpNoThrow(strOpToOp(op), packageName, uid, message)
-                != AppOpsManager.MODE_ALLOWED) {
-            return PERMISSION_DENIED_APP_OP;
+        if (forDataDelivery) {
+            if (appOpsManager.noteProxyOpNoThrow(op, packageName, uid, message)
+                    != AppOpsManager.MODE_ALLOWED) {
+                return PERMISSION_DENIED_APP_OP;
+            }
+        } else {
+            final int mode = appOpsManager.unsafeCheckOpRawNoThrow(op, uid, packageName);
+            if (mode != AppOpsManager.MODE_ALLOWED && mode != AppOpsManager.MODE_FOREGROUND) {
+                return PERMISSION_DENIED_APP_OP;
+            }
         }
 
         return PERMISSION_GRANTED;
     }
-
-    /**
-     * Checks whether your app has a given permission and whether the app op
-     * that corresponds to this permission is allowed.
-     *
-     * <p>This API assumes the the {@link Binder#getCallingUid()} is the same as
-     * {@link Process#myUid()}.
-     *
-     * @param context Context for accessing resources.
-     * @param permission The permission to check.
-     * @return The permission check result which is either {@link #PERMISSION_GRANTED}
-     *     or {@link #PERMISSION_DENIED} or {@link #PERMISSION_DENIED_APP_OP}.
-     */
-    @PermissionResult
-    public static int checkSelfPermission(@NonNull Context context,
-            @NonNull String permission) {
-        return checkPermission(context, permission, Process.myPid(),
-                Process.myUid(), context.getPackageName(), null /* self access */);
-    }
-
-    /**
-     * @deprecated Use {@link #checkCallingPermission(Context, String, String, String)} instead
-     */
-    @Deprecated
-    @PermissionResult
-    public static int checkCallingPermission(@NonNull Context context,
-            @NonNull String permission, @Nullable String packageName) {
-        return checkCallingPermission(context, permission, packageName, null);
-    }
-
-    /**
-     * Checks whether the IPC you are handling has a given permission and whether
-     * the app op that corresponds to this permission is allowed.
-     *
-     * @param context Context for accessing resources.
-     * @param permission The permission to check.
-     * @param packageName The package name making the IPC. If null the
-     *     the first package for the calling UID will be used.
-     * @param message A message describing the reason the permission was checked
-     *
-     * @return The permission check result which is either {@link #PERMISSION_GRANTED}
-     *     or {@link #PERMISSION_DENIED} or {@link #PERMISSION_DENIED_APP_OP}.
-     */
-    @PermissionResult
-    public static int checkCallingPermission(@NonNull Context context,
-            @NonNull String permission, @Nullable String packageName, @Nullable String message) {
-        if (Binder.getCallingPid() == Process.myPid()) {
-            return PERMISSION_DENIED;
-        }
-        return checkPermission(context, permission, Binder.getCallingPid(),
-                Binder.getCallingUid(), packageName, message);
-    }
-
-    /**
-     * @deprecated Use {@link #checkCallingOrSelfPermission(Context, String, String)} instead
-     */
-    @Deprecated
-    @PermissionResult
-    public static int checkCallingOrSelfPermission(@NonNull Context context,
-            @NonNull String permission) {
-        return checkCallingOrSelfPermission(context, permission, null);
-    }
-
-    /**
-     * Checks whether the IPC you are handling or your app has a given permission
-     * and whether the app op that corresponds to this permission is allowed.
-     *
-     * @param context Context for accessing resources.
-     * @param permission The permission to check.
-     * @param message A message describing the reason the permission was checked
-     *
-     * @return The permission check result which is either {@link #PERMISSION_GRANTED}
-     *     or {@link #PERMISSION_DENIED} or {@link #PERMISSION_DENIED_APP_OP}.
-     */
-    @PermissionResult
-    public static int checkCallingOrSelfPermission(@NonNull Context context,
-            @NonNull String permission, @Nullable String message) {
-        String packageName = (Binder.getCallingPid() == Process.myPid())
-                ? context.getPackageName() : null;
-        return checkPermission(context, permission, Binder.getCallingPid(),
-                Binder.getCallingUid(), packageName, message);
-    }
-}
+}
\ No newline at end of file
diff --git a/core/java/android/content/om/IOverlayManager.aidl b/core/java/android/content/om/IOverlayManager.aidl
index 43a4fe5..3d7e3be 100644
--- a/core/java/android/content/om/IOverlayManager.aidl
+++ b/core/java/android/content/om/IOverlayManager.aidl
@@ -157,4 +157,10 @@
      * Returns the list of default overlay packages, or an empty array if there are none.
      */
     String[] getDefaultOverlayPackages();
+
+    /**
+     * Invalidates and removes the idmap for an overlay,
+     * @param packageName The name of the overlay package whose idmap should be deleted.
+     */
+    void invalidateCachesForOverlay(in String packageName, in int userIs);
 }
diff --git a/core/java/android/content/om/OverlayManager.java b/core/java/android/content/om/OverlayManager.java
index f2716fe..a2f8886 100644
--- a/core/java/android/content/om/OverlayManager.java
+++ b/core/java/android/content/om/OverlayManager.java
@@ -21,6 +21,7 @@
 import android.annotation.RequiresPermission;
 import android.annotation.SystemApi;
 import android.annotation.SystemService;
+import android.annotation.TestApi;
 import android.content.Context;
 import android.os.RemoteException;
 import android.os.ServiceManager;
@@ -163,4 +164,27 @@
             throw e.rethrowFromSystemServer();
         }
     }
+
+    /**
+     * Clear part of the overlay manager's internal cache of PackageInfo
+     * objects. Only intended for testing.
+     *
+     * @param targetPackageName The name of the target package.
+     * @param user The user to get the OverlayInfos for.
+     *
+     * @hide
+     */
+    @TestApi
+    @RequiresPermission(anyOf = {
+            "android.permission.INTERACT_ACROSS_USERS",
+    })
+    @NonNull
+    public void invalidateCachesForOverlay(@NonNull final String targetPackageName,
+            @NonNull UserHandle user) {
+        try {
+            mService.invalidateCachesForOverlay(targetPackageName, user.getIdentifier());
+        } catch (RemoteException e) {
+            throw e.rethrowFromSystemServer();
+        }
+    }
 }
diff --git a/core/java/android/content/pm/AndroidTestBaseUpdater.java b/core/java/android/content/pm/AndroidTestBaseUpdater.java
index da1a693..8fcfe71 100644
--- a/core/java/android/content/pm/AndroidTestBaseUpdater.java
+++ b/core/java/android/content/pm/AndroidTestBaseUpdater.java
@@ -18,10 +18,17 @@
 import static android.content.pm.SharedLibraryNames.ANDROID_TEST_BASE;
 import static android.content.pm.SharedLibraryNames.ANDROID_TEST_RUNNER;
 
+import android.compat.annotation.ChangeId;
+import android.compat.annotation.EnabledAfter;
+import android.content.Context;
 import android.content.pm.PackageParser.Package;
 import android.os.Build;
+import android.os.RemoteException;
+import android.os.ServiceManager;
+import android.util.Log;
 
 import com.android.internal.annotations.VisibleForTesting;
+import com.android.internal.compat.IPlatformCompat;
 
 /**
  * Updates a package to ensure that if it targets <= Q that the android.test.base library is
@@ -37,10 +44,26 @@
  */
 @VisibleForTesting
 public class AndroidTestBaseUpdater extends PackageSharedLibraryUpdater {
+    private static final String TAG = "AndroidTestBaseUpdater";
 
-    private static boolean apkTargetsApiLevelLessThanOrEqualToQ(Package pkg) {
-        int targetSdkVersion = pkg.applicationInfo.targetSdkVersion;
-        return targetSdkVersion <= Build.VERSION_CODES.Q;
+    /**
+     * Remove android.test.base library for apps that target SDK R or more and do not depend on
+     * android.test.runner (as it depends on classes from the android.test.base library).
+     */
+    @ChangeId
+    @EnabledAfter(targetSdkVersion = Build.VERSION_CODES.Q)
+    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);
+        }
+        // Fall back to previous behaviour.
+        return pkg.applicationInfo.targetSdkVersion <= Build.VERSION_CODES.Q;
     }
 
     @Override
@@ -48,7 +71,7 @@
         // Packages targeted at <= Q expect the classes in the android.test.base library
         // to be accessible so this maintains backward compatibility by adding the
         // android.test.base library to those packages.
-        if (apkTargetsApiLevelLessThanOrEqualToQ(pkg)) {
+        if (!isChangeEnabled(pkg)) {
             prefixRequiredLibrary(pkg, ANDROID_TEST_BASE);
         } else {
             // If a package already depends on android.test.runner then add a dependency on
diff --git a/core/java/android/content/pm/IPackageManager.aidl b/core/java/android/content/pm/IPackageManager.aidl
index 4d7c43a..19d8edf 100644
--- a/core/java/android/content/pm/IPackageManager.aidl
+++ b/core/java/android/content/pm/IPackageManager.aidl
@@ -686,6 +686,8 @@
 
     String getSystemCaptionsServicePackageName();
 
+    String getSetupWizardPackageName();
+
     String getIncidentReportApproverPackageName();
 
     boolean isPackageStateProtected(String packageName, int userId);
diff --git a/core/java/android/content/pm/PackageInstaller.java b/core/java/android/content/pm/PackageInstaller.java
index 1099d8b..69ce3bd 100644
--- a/core/java/android/content/pm/PackageInstaller.java
+++ b/core/java/android/content/pm/PackageInstaller.java
@@ -101,19 +101,6 @@
  * <p>
  * The ApiDemos project contains examples of using this API:
  * <code>ApiDemos/src/com/example/android/apis/content/InstallApk*.java</code>.
- * <p>
- * On Android Q or above, an app installed notification will be posted
- * by system after a new app is installed.
- * To customize installer's notification icon, you should declare the following in the manifest
- * &lt;application> as follows: </p>
- * <pre>
- * &lt;meta-data android:name="com.android.packageinstaller.notification.smallIcon"
- * android:resource="@drawable/installer_notification_icon"/>
- * </pre>
- * <pre>
- * &lt;meta-data android:name="com.android.packageinstaller.notification.color"
- * android:resource="@color/installer_notification_color"/>
- * </pre>
  */
 public class PackageInstaller {
     private static final String TAG = "PackageInstaller";
diff --git a/core/java/android/content/pm/PackageManager.java b/core/java/android/content/pm/PackageManager.java
index fd14d23..9513ce8 100644
--- a/core/java/android/content/pm/PackageManager.java
+++ b/core/java/android/content/pm/PackageManager.java
@@ -7427,6 +7427,17 @@
     }
 
     /**
+     * @return the system defined setup wizard package name, or null if there's none.
+     *
+     * @hide
+     */
+    @Nullable
+    public String getSetupWizardPackageName() {
+        throw new UnsupportedOperationException(
+                "getSetupWizardPackageName not implemented in subclass");
+    }
+
+    /**
      * @return the incident report approver app package name, or null if it's not defined
      * by the OEM.
      *
diff --git a/core/java/android/content/pm/UserInfo.java b/core/java/android/content/pm/UserInfo.java
index df652f1..ccfa184 100644
--- a/core/java/android/content/pm/UserInfo.java
+++ b/core/java/android/content/pm/UserInfo.java
@@ -187,6 +187,18 @@
     @UnsupportedAppUsage
     public boolean guestToRemove;
 
+    /**
+     * This is used to optimize the creation of an user, i.e. OEMs might choose to pre-create a
+     * number of users at the first boot, so the actual creation later is faster.
+     *
+     * <p>A {@code preCreated} user is not a real user yet, so it should not show up on regular
+     * user operations (other than user creation per se).
+     *
+     * <p>Once the pre-created is used to create a "real" user later on, {@code preCreate} is set to
+     * {@code false}.
+     */
+    public boolean preCreated;
+
     @UnsupportedAppUsage
     public UserInfo(int id, String name, int flags) {
         this(id, name, null, flags);
@@ -214,6 +226,13 @@
 
     @UnsupportedAppUsage
     public boolean isGuest() {
+        return isGuest(flags);
+    }
+
+    /**
+     * Checks if the flag denotes a guest user.
+     */
+    public static boolean isGuest(@UserInfoFlag int flags) {
         return (flags & FLAG_GUEST) == FLAG_GUEST;
     }
 
@@ -224,6 +243,13 @@
 
     @UnsupportedAppUsage
     public boolean isManagedProfile() {
+        return isManagedProfile(flags);
+    }
+
+    /**
+     * Checks if the flag denotes a managed profile.
+     */
+    public static boolean isManagedProfile(@UserInfoFlag int flags) {
         return (flags & FLAG_MANAGED_PROFILE) == FLAG_MANAGED_PROFILE;
     }
 
@@ -315,6 +341,7 @@
         lastLoggedInTime = orig.lastLoggedInTime;
         lastLoggedInFingerprint = orig.lastLoggedInFingerprint;
         partial = orig.partial;
+        preCreated = orig.preCreated;
         profileGroupId = orig.profileGroupId;
         restrictedProfileParentId = orig.restrictedProfileParentId;
         guestToRemove = orig.guestToRemove;
@@ -323,7 +350,7 @@
 
     @UnsupportedAppUsage
     public UserHandle getUserHandle() {
-        return new UserHandle(id);
+        return UserHandle.of(id);
     }
 
     @Override
@@ -339,6 +366,8 @@
         return "UserInfo[id=" + id
                 + ", name=" + name
                 + ", flags=" + flagsToString(flags)
+                + (preCreated ? " (pre-created)" : "")
+                + (partial ? " (partial)" : "")
                 + "]";
     }
 
@@ -362,9 +391,10 @@
         dest.writeLong(creationTime);
         dest.writeLong(lastLoggedInTime);
         dest.writeString(lastLoggedInFingerprint);
-        dest.writeInt(partial ? 1 : 0);
+        dest.writeBoolean(partial);
+        dest.writeBoolean(preCreated);
         dest.writeInt(profileGroupId);
-        dest.writeInt(guestToRemove ? 1 : 0);
+        dest.writeBoolean(guestToRemove);
         dest.writeInt(restrictedProfileParentId);
         dest.writeInt(profileBadge);
     }
@@ -389,9 +419,10 @@
         creationTime = source.readLong();
         lastLoggedInTime = source.readLong();
         lastLoggedInFingerprint = source.readString();
-        partial = source.readInt() != 0;
+        partial = source.readBoolean();
+        preCreated = source.readBoolean();
         profileGroupId = source.readInt();
-        guestToRemove = source.readInt() != 0;
+        guestToRemove = source.readBoolean();
         restrictedProfileParentId = source.readInt();
         profileBadge = source.readInt();
     }
diff --git a/core/java/android/content/res/ApkAssets.java b/core/java/android/content/res/ApkAssets.java
index 69462ab..a35ad56 100644
--- a/core/java/android/content/res/ApkAssets.java
+++ b/core/java/android/content/res/ApkAssets.java
@@ -188,7 +188,7 @@
     /**
      * Closes this class and the contained {@link #mStringBlock}.
      */
-    public void close() throws Throwable {
+    public void close() {
         synchronized (this) {
             if (mOpen) {
                 mOpen = false;
diff --git a/core/java/android/content/res/StringBlock.java b/core/java/android/content/res/StringBlock.java
index b7bc822..2ae1932 100644
--- a/core/java/android/content/res/StringBlock.java
+++ b/core/java/android/content/res/StringBlock.java
@@ -175,7 +175,7 @@
         }
     }
 
-    public void close() throws Throwable {
+    public void close() {
         synchronized (this) {
             if (mOpen) {
                 mOpen = false;
diff --git a/core/java/android/hardware/biometrics/IBiometricConfirmDeviceCredentialCallback.aidl b/core/java/android/hardware/biometrics/Authenticator.java
similarity index 62%
copy from core/java/android/hardware/biometrics/IBiometricConfirmDeviceCredentialCallback.aidl
copy to core/java/android/hardware/biometrics/Authenticator.java
index 8b35852..6d7e748 100644
--- a/core/java/android/hardware/biometrics/IBiometricConfirmDeviceCredentialCallback.aidl
+++ b/core/java/android/hardware/biometrics/Authenticator.java
@@ -17,10 +17,19 @@
 package android.hardware.biometrics;
 
 /**
- * Communication channel between ConfirmDeviceCredential / ConfirmLock* and BiometricService.
+ * Type of authenticators defined on a granularity that the BiometricManager / BiometricPrompt
+ * supports.
  * @hide
  */
-interface IBiometricConfirmDeviceCredentialCallback {
-    // Invoked when authentication should be canceled.
-    oneway void cancel();
-}
\ No newline at end of file
+public class Authenticator {
+
+    /**
+     * Device credential, e.g. Pin/Pattern/Password.
+     */
+    public static final int TYPE_CREDENTIAL = 1 << 0;
+    /**
+     * Encompasses all biometrics on the device, e.g. Fingerprint/Iris/Face.
+     */
+    public static final int TYPE_BIOMETRIC = 1 << 1;
+
+}
diff --git a/core/java/android/hardware/biometrics/BiometricManager.java b/core/java/android/hardware/biometrics/BiometricManager.java
index d8110f3..cbe8a05 100644
--- a/core/java/android/hardware/biometrics/BiometricManager.java
+++ b/core/java/android/hardware/biometrics/BiometricManager.java
@@ -201,55 +201,5 @@
         }
     }
 
-    /**
-     * TODO(b/123378871): Remove when moved.
-     * @hide
-     */
-    @RequiresPermission(USE_BIOMETRIC_INTERNAL)
-    public void onConfirmDeviceCredentialSuccess() {
-        if (mService != null) {
-            try {
-                mService.onConfirmDeviceCredentialSuccess();
-            } catch (RemoteException e) {
-                throw e.rethrowFromSystemServer();
-            }
-        } else {
-            Slog.w(TAG, "onConfirmDeviceCredentialSuccess(): Service not connected");
-        }
-    }
-
-    /**
-     * TODO(b/123378871): Remove when moved.
-     * @hide
-     */
-    @RequiresPermission(USE_BIOMETRIC_INTERNAL)
-    public void onConfirmDeviceCredentialError(int error, String message) {
-        if (mService != null) {
-            try {
-                mService.onConfirmDeviceCredentialError(error, message);
-            } catch (RemoteException e) {
-                throw e.rethrowFromSystemServer();
-            }
-        } else {
-            Slog.w(TAG, "onConfirmDeviceCredentialError(): Service not connected");
-        }
-    }
-
-    /**
-     * TODO(b/123378871): Remove when moved.
-     * @hide
-     */
-    @RequiresPermission(USE_BIOMETRIC_INTERNAL)
-    public void registerCancellationCallback(IBiometricConfirmDeviceCredentialCallback callback) {
-        if (mService != null) {
-            try {
-                mService.registerCancellationCallback(callback);
-            } catch (RemoteException e) {
-                throw e.rethrowFromSystemServer();
-            }
-        } else {
-            Slog.w(TAG, "registerCancellationCallback(): Service not connected");
-        }
-    }
 }
 
diff --git a/core/java/android/hardware/biometrics/BiometricPrompt.java b/core/java/android/hardware/biometrics/BiometricPrompt.java
index fb6b231..cf86e251 100644
--- a/core/java/android/hardware/biometrics/BiometricPrompt.java
+++ b/core/java/android/hardware/biometrics/BiometricPrompt.java
@@ -69,24 +69,21 @@
     /**
      * @hide
      */
-    public static final String KEY_POSITIVE_TEXT = "positive_text";
-    /**
-     * @hide
-     */
     public static final String KEY_NEGATIVE_TEXT = "negative_text";
     /**
      * @hide
      */
     public static final String KEY_REQUIRE_CONFIRMATION = "require_confirmation";
     /**
+     * This is deprecated. Internally we should use {@link #KEY_AUTHENTICATORS_ALLOWED}
      * @hide
      */
     public static final String KEY_ALLOW_DEVICE_CREDENTIAL = "allow_device_credential";
     /**
+     * If this key is set, we will ignore {@link #KEY_ALLOW_DEVICE_CREDENTIAL}
      * @hide
      */
-    public static final String KEY_FROM_CONFIRM_DEVICE_CREDENTIAL
-            = "from_confirm_device_credential";
+    public static final String KEY_AUTHENTICATORS_ALLOWED = "authenticators_allowed";
 
     /**
      * Error/help message will show for this amount of time.
@@ -100,7 +97,7 @@
     /**
      * @hide
      */
-    public static final int DISMISSED_REASON_CONFIRMED = 1;
+    public static final int DISMISSED_REASON_BIOMETRIC_CONFIRMED = 1;
 
     /**
      * Dialog is done animating away after user clicked on the button set via
@@ -119,7 +116,7 @@
      * Authenticated, confirmation not required. Dialog animated away.
      * @hide
      */
-    public static final int DISMISSED_REASON_CONFIRM_NOT_REQUIRED = 4;
+    public static final int DISMISSED_REASON_BIOMETRIC_CONFIRM_NOT_REQUIRED = 4;
 
     /**
      * Error message shown on SystemUI. When BiometricService receives this, the UI is already
@@ -134,6 +131,11 @@
      */
     public static final int DISMISSED_REASON_SERVER_REQUESTED = 6;
 
+    /**
+     * @hide
+     */
+    public static final int DISMISSED_REASON_CREDENTIAL_CONFIRMED = 7;
+
     private static class ButtonInfo {
         Executor executor;
         DialogInterface.OnClickListener listener;
@@ -203,30 +205,6 @@
         }
 
         /**
-         * Optional: Set the text for the positive button. If not set, the positive button
-         * will not show.
-         * @param text
-         * @return
-         * @hide
-         */
-        @NonNull public Builder setPositiveButton(@NonNull CharSequence text,
-                @NonNull @CallbackExecutor Executor executor,
-                @NonNull DialogInterface.OnClickListener listener) {
-            if (TextUtils.isEmpty(text)) {
-                throw new IllegalArgumentException("Text must be set and non-empty");
-            }
-            if (executor == null) {
-                throw new IllegalArgumentException("Executor must not be null");
-            }
-            if (listener == null) {
-                throw new IllegalArgumentException("Listener must not be null");
-            }
-            mBundle.putCharSequence(KEY_POSITIVE_TEXT, text);
-            mPositiveButtonInfo = new ButtonInfo(executor, listener);
-            return this;
-        }
-
-        /**
          * Required: Set the text for the negative button. This would typically be used as a
          * "Cancel" button, but may be also used to show an alternative method for authentication,
          * such as screen that asks for a backup password.
@@ -298,17 +276,6 @@
         }
 
         /**
-         * TODO(123378871): Remove when moved.
-         * @return
-         * @hide
-         */
-        @RequiresPermission(USE_BIOMETRIC_INTERNAL)
-        @NonNull public Builder setFromConfirmDeviceCredential() {
-            mBundle.putBoolean(KEY_FROM_CONFIRM_DEVICE_CREDENTIAL, true);
-            return this;
-        }
-
-        /**
          * Creates a {@link BiometricPrompt}.
          * @return a {@link BiometricPrompt}
          * @throws IllegalArgumentException if any of the required fields are not set.
@@ -317,15 +284,19 @@
             final CharSequence title = mBundle.getCharSequence(KEY_TITLE);
             final CharSequence negative = mBundle.getCharSequence(KEY_NEGATIVE_TEXT);
             final boolean useDefaultTitle = mBundle.getBoolean(KEY_USE_DEFAULT_TITLE);
-            final boolean enableFallback = mBundle.getBoolean(KEY_ALLOW_DEVICE_CREDENTIAL);
+            final boolean allowCredential = mBundle.getBoolean(KEY_ALLOW_DEVICE_CREDENTIAL);
+            final Object authenticatorsAllowed = mBundle.get(KEY_AUTHENTICATORS_ALLOWED);
 
             if (TextUtils.isEmpty(title) && !useDefaultTitle) {
                 throw new IllegalArgumentException("Title must be set and non-empty");
-            } else if (TextUtils.isEmpty(negative) && !enableFallback) {
+            } else if (TextUtils.isEmpty(negative) && !allowCredential) {
                 throw new IllegalArgumentException("Negative text must be set and non-empty");
-            } else if (!TextUtils.isEmpty(negative) && enableFallback) {
+            } else if (!TextUtils.isEmpty(negative) && allowCredential) {
                 throw new IllegalArgumentException("Can't have both negative button behavior"
                         + " and device credential enabled");
+            } else if (authenticatorsAllowed != null && allowCredential) {
+                throw new IllegalArgumentException("setAuthenticatorsAllowed and"
+                        + " setDeviceCredentialAllowed should not be used simultaneously");
             }
             return new BiometricPrompt(mContext, mBundle, mPositiveButtonInfo, mNegativeButtonInfo);
         }
@@ -384,7 +355,7 @@
         @Override
         public void onDialogDismissed(int reason) throws RemoteException {
             // Check the reason and invoke OnClickListener(s) if necessary
-            if (reason == DISMISSED_REASON_CONFIRMED) {
+            if (reason == DISMISSED_REASON_BIOMETRIC_CONFIRMED) {
                 mPositiveButtonInfo.executor.execute(() -> {
                     mPositiveButtonInfo.listener.onClick(null, DialogInterface.BUTTON_POSITIVE);
                 });
@@ -532,8 +503,7 @@
     public void authenticateUser(@NonNull CancellationSignal cancel,
             @NonNull @CallbackExecutor Executor executor,
             @NonNull AuthenticationCallback callback,
-            int userId,
-            IBiometricConfirmDeviceCredentialCallback confirmDeviceCredentialCallback) {
+            int userId) {
         if (cancel == null) {
             throw new IllegalArgumentException("Must supply a cancellation signal");
         }
@@ -543,8 +513,7 @@
         if (callback == null) {
             throw new IllegalArgumentException("Must supply a callback");
         }
-        authenticateInternal(null /* crypto */, cancel, executor, callback, userId,
-                confirmDeviceCredentialCallback);
+        authenticateInternal(null /* crypto */, cancel, executor, callback, userId);
     }
 
     /**
@@ -595,8 +564,7 @@
         if (mBundle.getBoolean(KEY_ALLOW_DEVICE_CREDENTIAL)) {
             throw new IllegalArgumentException("Device credential not supported with crypto");
         }
-        authenticateInternal(crypto, cancel, executor, callback, mContext.getUserId(),
-                null /* confirmDeviceCredentialCallback */);
+        authenticateInternal(crypto, cancel, executor, callback, mContext.getUserId());
     }
 
     /**
@@ -638,8 +606,7 @@
         if (callback == null) {
             throw new IllegalArgumentException("Must supply a callback");
         }
-        authenticateInternal(null /* crypto */, cancel, executor, callback, mContext.getUserId(),
-                null /* confirmDeviceCredentialCallback */);
+        authenticateInternal(null /* crypto */, cancel, executor, callback, mContext.getUserId());
     }
 
     private void cancelAuthentication() {
@@ -656,8 +623,7 @@
             @NonNull CancellationSignal cancel,
             @NonNull @CallbackExecutor Executor executor,
             @NonNull AuthenticationCallback callback,
-            int userId,
-            IBiometricConfirmDeviceCredentialCallback confirmDeviceCredentialCallback) {
+            int userId) {
         try {
             if (cancel.isCanceled()) {
                 Log.w(TAG, "Authentication already canceled");
@@ -672,7 +638,7 @@
             final long sessionId = crypto != null ? crypto.getOpId() : 0;
             if (BiometricManager.hasBiometrics(mContext)) {
                 mService.authenticate(mToken, sessionId, userId, mBiometricServiceReceiver,
-                        mContext.getOpPackageName(), mBundle, confirmDeviceCredentialCallback);
+                        mContext.getOpPackageName(), mBundle);
             } else {
                 mExecutor.execute(() -> {
                     callback.onAuthenticationError(BiometricPrompt.BIOMETRIC_ERROR_HW_NOT_PRESENT,
diff --git a/core/java/android/hardware/biometrics/IBiometricService.aidl b/core/java/android/hardware/biometrics/IBiometricService.aidl
index f0a0b2f..6a3bf38 100644
--- a/core/java/android/hardware/biometrics/IBiometricService.aidl
+++ b/core/java/android/hardware/biometrics/IBiometricService.aidl
@@ -17,7 +17,6 @@
 package android.hardware.biometrics;
 
 import android.os.Bundle;
-import android.hardware.biometrics.IBiometricConfirmDeviceCredentialCallback;
 import android.hardware.biometrics.IBiometricEnabledOnKeyguardCallback;
 import android.hardware.biometrics.IBiometricServiceReceiver;
 
@@ -31,10 +30,8 @@
 interface IBiometricService {
     // Requests authentication. The service choose the appropriate biometric to use, and show
     // the corresponding BiometricDialog.
-    // TODO(b/123378871): Remove callback when moved.
     void authenticate(IBinder token, long sessionId, int userId,
-            IBiometricServiceReceiver receiver, String opPackageName, in Bundle bundle,
-            IBiometricConfirmDeviceCredentialCallback callback);
+            IBiometricServiceReceiver receiver, String opPackageName, in Bundle bundle);
 
     // Cancel authentication for the given sessionId
     void cancelAuthentication(IBinder token, String opPackageName);
@@ -57,16 +54,4 @@
 
     // Reset the lockout when user authenticates with strong auth (e.g. PIN, pattern or password)
     void resetLockout(in byte [] token);
-
-    // TODO(b/123378871): Remove when moved.
-    // CDCA needs to send results to BiometricService if it was invoked using BiometricPrompt's
-    // setAllowDeviceCredential method, since there's no way for us to intercept onActivityResult.
-    // CDCA is launched from BiometricService (startActivityAsUser) instead of *ForResult.
-    void onConfirmDeviceCredentialSuccess();
-    // TODO(b/123378871): Remove when moved.
-    void onConfirmDeviceCredentialError(int error, String message);
-    // TODO(b/123378871): Remove when moved.
-    // When ConfirmLock* is invoked from BiometricPrompt, it needs to register a callback so that
-    // it can receive the cancellation signal.
-    void registerCancellationCallback(IBiometricConfirmDeviceCredentialCallback callback);
 }
diff --git a/core/java/android/hardware/biometrics/IBiometricServiceReceiverInternal.aidl b/core/java/android/hardware/biometrics/IBiometricServiceReceiverInternal.aidl
index ca6114e..66b6e89 100644
--- a/core/java/android/hardware/biometrics/IBiometricServiceReceiverInternal.aidl
+++ b/core/java/android/hardware/biometrics/IBiometricServiceReceiverInternal.aidl
@@ -38,4 +38,6 @@
     void onDialogDismissed(int reason);
     // Notifies that the user has pressed the "try again" button on SystemUI
     void onTryAgainPressed();
+    // Notifies that the user has pressed the "use password" button on SystemUI
+    void onDeviceCredentialPressed();
 }
diff --git a/core/java/android/hardware/location/ContextHubClientCallback.java b/core/java/android/hardware/location/ContextHubClientCallback.java
index cc2fe65..20fa753 100644
--- a/core/java/android/hardware/location/ContextHubClientCallback.java
+++ b/core/java/android/hardware/location/ContextHubClientCallback.java
@@ -66,7 +66,9 @@
     public void onNanoAppAborted(ContextHubClient client, long nanoAppId, int abortCode) {}
 
     /**
-     * Callback invoked when a nanoapp is loaded at the attached Context Hub.
+     * Callback invoked when a nanoapp is dynamically loaded at the attached Context Hub through
+     * the {@link android.hardware.location.ContextHubManager}. This callback is not invoked for a
+     * nanoapp that is loaded internally by CHRE (e.g. nanoapps that are preloaded by the system).
      *
      * @param client the client that is associated with this callback
      * @param nanoAppId the ID of the nanoapp that had been loaded
@@ -74,7 +76,8 @@
     public void onNanoAppLoaded(ContextHubClient client, long nanoAppId) {}
 
     /**
-     * Callback invoked when a nanoapp is unloaded from the attached Context Hub.
+     * Callback invoked when a nanoapp is dynamically unloaded from the attached Context Hub through
+     * the {@link android.hardware.location.ContextHubManager}.
      *
      * @param client the client that is associated with this callback
      * @param nanoAppId the ID of the nanoapp that had been unloaded
@@ -82,7 +85,8 @@
     public void onNanoAppUnloaded(ContextHubClient client, long nanoAppId) {}
 
     /**
-     * Callback invoked when a nanoapp is enabled at the attached Context Hub.
+     * Callback invoked when a nanoapp is dynamically enabled at the attached Context Hub through
+     * the {@link android.hardware.location.ContextHubManager}.
      *
      * @param client the client that is associated with this callback
      * @param nanoAppId the ID of the nanoapp that had been enabled
@@ -90,7 +94,8 @@
     public void onNanoAppEnabled(ContextHubClient client, long nanoAppId) {}
 
     /**
-     * Callback invoked when a nanoapp is disabled at the attached Context Hub.
+     * Callback invoked when a nanoapp is dynamically disabled at the attached Context Hub through
+     * the {@link android.hardware.location.ContextHubManager}.
      *
      * @param client the client that is associated with this callback
      * @param nanoAppId the ID of the nanoapp that had been disabled
diff --git a/core/java/android/hardware/usb/UsbDevice.java b/core/java/android/hardware/usb/UsbDevice.java
index 08c9eea..11f4ffb 100644
--- a/core/java/android/hardware/usb/UsbDevice.java
+++ b/core/java/android/hardware/usb/UsbDevice.java
@@ -60,6 +60,9 @@
     private final int mClass;
     private final int mSubclass;
     private final int mProtocol;
+    private final boolean mHasAudioPlayback;
+    private final boolean mHasAudioCapture;
+    private final boolean mHasMidi;
 
     /** All interfaces on the device. Initialized on first call to getInterfaceList */
     @UnsupportedAppUsage
@@ -73,7 +76,8 @@
     private UsbDevice(@NonNull String name, int vendorId, int productId, int Class, int subClass,
             int protocol, @Nullable String manufacturerName, @Nullable String productName,
             @NonNull String version, @NonNull UsbConfiguration[] configurations,
-            @NonNull IUsbSerialReader serialNumberReader) {
+            @NonNull IUsbSerialReader serialNumberReader,
+            boolean hasAudioPlayback, boolean hasAudioCapture, boolean hasMidi) {
         mName = Preconditions.checkNotNull(name);
         mVendorId = vendorId;
         mProductId = productId;
@@ -85,6 +89,9 @@
         mVersion = Preconditions.checkStringNotEmpty(version);
         mConfigurations = Preconditions.checkArrayElementsNotNull(configurations, "configurations");
         mSerialNumberReader = Preconditions.checkNotNull(serialNumberReader);
+        mHasAudioPlayback = hasAudioPlayback;
+        mHasAudioCapture = hasAudioCapture;
+        mHasMidi = hasMidi;
 
         // Make sure the binder belongs to the system
         if (ActivityThread.isSystem()) {
@@ -214,6 +221,21 @@
         return mConfigurations.length;
     }
 
+    /** @hide */
+    public boolean getHasAudioPlayback() {
+        return mHasAudioPlayback;
+    }
+
+    /** @hide */
+    public boolean getHasAudioCapture() {
+        return mHasAudioCapture;
+    }
+
+    /** @hide */
+    public boolean getHasMidi() {
+        return mHasMidi;
+    }
+
     /**
      * Returns the {@link UsbConfiguration} at the given index.
      *
@@ -286,12 +308,15 @@
 
     @Override
     public String toString() {
-        StringBuilder builder = new StringBuilder("UsbDevice[mName=" + mName +
-                ",mVendorId=" + mVendorId + ",mProductId=" + mProductId +
-                ",mClass=" + mClass + ",mSubclass=" + mSubclass + ",mProtocol=" + mProtocol +
-                ",mManufacturerName=" + mManufacturerName + ",mProductName=" + mProductName +
-                ",mVersion=" + mVersion + ",mSerialNumberReader=" + mSerialNumberReader
-                + ",mConfigurations=[");
+        StringBuilder builder = new StringBuilder("UsbDevice[mName=" + mName
+                + ",mVendorId=" + mVendorId + ",mProductId=" + mProductId
+                + ",mClass=" + mClass + ",mSubclass=" + mSubclass + ",mProtocol=" + mProtocol
+                + ",mManufacturerName=" + mManufacturerName + ",mProductName=" + mProductName
+                + ",mVersion=" + mVersion + ",mSerialNumberReader=" + mSerialNumberReader
+                + ", mHasAudioPlayback=" + mHasAudioPlayback
+                + ", mHasAudioCapture=" + mHasAudioCapture
+                + ", mHasMidi=" + mHasMidi
+                + ", mConfigurations=[");
         for (int i = 0; i < mConfigurations.length; i++) {
             builder.append("\n");
             builder.append(mConfigurations[i].toString());
@@ -316,9 +341,15 @@
                     IUsbSerialReader.Stub.asInterface(in.readStrongBinder());
             UsbConfiguration[] configurations = in.readParcelableArray(
                     UsbConfiguration.class.getClassLoader(), UsbConfiguration.class);
+            // Capabilities
+            boolean hasAudioPlayback = in.readInt() == 1;
+            boolean hasAudioCapture = in.readInt() == 1;
+            boolean hasMidi = in.readInt() == 1;
+
             UsbDevice device = new UsbDevice(name, vendorId, productId, clasz, subClass, protocol,
-                                 manufacturerName, productName, version, configurations,
-                    serialNumberReader);
+                    manufacturerName, productName, version, configurations, serialNumberReader,
+                    hasAudioPlayback, hasAudioCapture, hasMidi);
+
             return device;
         }
 
@@ -343,7 +374,10 @@
         parcel.writeString(mVersion);
         parcel.writeStrongBinder(mSerialNumberReader.asBinder());
         parcel.writeParcelableArray(mConfigurations, 0);
-   }
+        parcel.writeInt(mHasAudioPlayback ? 1 : 0);
+        parcel.writeInt(mHasAudioCapture ? 1 : 0);
+        parcel.writeInt(mHasMidi ? 1 : 0);
+    }
 
     public static int getDeviceId(String name) {
         return native_get_device_id(name);
@@ -370,6 +404,9 @@
         private final @Nullable String mProductName;
         private final @NonNull String mVersion;
         private final @NonNull UsbConfiguration[] mConfigurations;
+        private final boolean mHasAudioPlayback;
+        private final boolean mHasAudioCapture;
+        private final boolean mHasMidi;
 
         // Temporary storage for serial number. Serial number reader need to be wrapped in a
         // IUsbSerialReader as they might be used as PII.
@@ -378,7 +415,8 @@
         public Builder(@NonNull String name, int vendorId, int productId, int Class, int subClass,
                 int protocol, @Nullable String manufacturerName, @Nullable String productName,
                 @NonNull String version, @NonNull UsbConfiguration[] configurations,
-                @Nullable String serialNumber) {
+                @Nullable String serialNumber,
+                boolean hasAudioPlayback, boolean hasAudioCapture, boolean hasMidi) {
             mName = Preconditions.checkNotNull(name);
             mVendorId = vendorId;
             mProductId = productId;
@@ -390,6 +428,9 @@
             mVersion = Preconditions.checkStringNotEmpty(version);
             mConfigurations = configurations;
             this.serialNumber = serialNumber;
+            mHasAudioPlayback = hasAudioPlayback;
+            mHasAudioCapture = hasAudioCapture;
+            mHasMidi = hasMidi;
         }
 
         /**
@@ -401,7 +442,8 @@
          */
         public UsbDevice build(@NonNull IUsbSerialReader serialReader) {
             return new UsbDevice(mName, mVendorId, mProductId, mClass, mSubclass, mProtocol,
-                    mManufacturerName, mProductName, mVersion, mConfigurations, serialReader);
+                    mManufacturerName, mProductName, mVersion, mConfigurations, serialReader,
+                    mHasAudioPlayback, mHasAudioCapture, mHasMidi);
         }
     }
 }
diff --git a/core/java/android/net/ConnectivityManager.java b/core/java/android/net/ConnectivityManager.java
index 111a8c4..5c65238 100644
--- a/core/java/android/net/ConnectivityManager.java
+++ b/core/java/android/net/ConnectivityManager.java
@@ -3265,42 +3265,77 @@
 
         /**
          * Called when the framework connects and has declared a new network ready for use.
-         * This callback may be called more than once if the {@link Network} that is
-         * satisfying the request changes. This will always immediately be followed by a
-         * call to {@link #onCapabilitiesChanged(Network, NetworkCapabilities)} then by a
-         * call to {@link #onLinkPropertiesChanged(Network, LinkProperties)}, and a call to
-         * {@link #onBlockedStatusChanged(Network, boolean)}.
+         *
+         * <p>For callbacks registered with {@link #registerNetworkCallback}, multiple networks may
+         * be available at the same time, and onAvailable will be called for each of these as they
+         * appear.
+         *
+         * <p>For callbacks registered with {@link #requestNetwork} and
+         * {@link #registerDefaultNetworkCallback}, this means the network passed as an argument
+         * is the new best network for this request and is now tracked by this callback ; this
+         * callback will no longer receive method calls about other networks that may have been
+         * passed to this method previously. The previously-best network may have disconnected, or
+         * it may still be around and the newly-best network may simply be better.
+         *
+         * <p>Starting with {@link android.os.Build.VERSION_CODES#O}, this will always immediately
+         * be followed by a call to {@link #onCapabilitiesChanged(Network, NetworkCapabilities)}
+         * then by a call to {@link #onLinkPropertiesChanged(Network, LinkProperties)}, and a call
+         * to {@link #onBlockedStatusChanged(Network, boolean)}.
+         *
+         * <p>Do NOT call {@link #getNetworkCapabilities(Network)} or
+         * {@link #getLinkProperties(Network)} or other synchronous ConnectivityManager methods in
+         * this callback as this is prone to race conditions (there is no guarantee the objects
+         * returned by these methods will be current). Instead, wait for a call to
+         * {@link #onCapabilitiesChanged(Network, NetworkCapabilities)} and
+         * {@link #onLinkPropertiesChanged(Network, LinkProperties)} whose arguments are guaranteed
+         * to be well-ordered with respect to other callbacks.
          *
          * @param network The {@link Network} of the satisfying network.
          */
         public void onAvailable(@NonNull Network network) {}
 
         /**
-         * Called when the network is about to be disconnected.  Often paired with an
-         * {@link NetworkCallback#onAvailable} call with the new replacement network
-         * for graceful handover.  This may not be called if we have a hard loss
-         * (loss without warning).  This may be followed by either a
-         * {@link NetworkCallback#onLost} call or a
-         * {@link NetworkCallback#onAvailable} call for this network depending
-         * on whether we lose or regain it.
+         * Called when the network is about to be lost, typically because there are no outstanding
+         * requests left for it. This may be paired with a {@link NetworkCallback#onAvailable} call
+         * with the new replacement network for graceful handover. This method is not guaranteed
+         * to be called before {@link NetworkCallback#onLost} is called, for example in case a
+         * network is suddenly disconnected.
          *
-         * @param network The {@link Network} that is about to be disconnected.
-         * @param maxMsToLive The time in ms the framework will attempt to keep the
-         *                     network connected.  Note that the network may suffer a
-         *                     hard loss at any time.
+         * <p>Do NOT call {@link #getNetworkCapabilities(Network)} or
+         * {@link #getLinkProperties(Network)} or other synchronous ConnectivityManager methods in
+         * this callback as this is prone to race conditions ; calling these methods while in a
+         * callback may return an outdated or even a null object.
+         *
+         * @param network The {@link Network} that is about to be lost.
+         * @param maxMsToLive The time in milliseconds the system intends to keep the network
+         *                    connected for graceful handover; note that the network may still
+         *                    suffer a hard loss at any time.
          */
         public void onLosing(@NonNull Network network, int maxMsToLive) {}
 
         /**
-         * Called when the framework has a hard loss of the network or when the
-         * graceful failure ends.
+         * Called when a network disconnects or otherwise no longer satisfies this request or
+         * callback.
+         *
+         * <p>If the callback was registered with requestNetwork() or
+         * registerDefaultNetworkCallback(), it will only be invoked against the last network
+         * returned by onAvailable() when that network is lost and no other network satisfies
+         * the criteria of the request.
+         *
+         * <p>If the callback was registered with registerNetworkCallback() it will be called for
+         * each network which no longer satisfies the criteria of the callback.
+         *
+         * <p>Do NOT call {@link #getNetworkCapabilities(Network)} or
+         * {@link #getLinkProperties(Network)} or other synchronous ConnectivityManager methods in
+         * this callback as this is prone to race conditions ; calling these methods while in a
+         * callback may return an outdated or even a null object.
          *
          * @param network The {@link Network} lost.
          */
         public void onLost(@NonNull Network network) {}
 
         /**
-         * Called if no network is found in the timeout time specified in
+         * Called if no network is found within the timeout time specified in
          * {@link #requestNetwork(NetworkRequest, NetworkCallback, int)} call or if the
          * requested network request cannot be fulfilled (whether or not a timeout was
          * specified). When this callback is invoked the associated
@@ -3310,8 +3345,15 @@
         public void onUnavailable() {}
 
         /**
-         * Called when the network the framework connected to for this request
-         * changes capabilities but still satisfies the stated need.
+         * Called when the network corresponding to this request changes capabilities but still
+         * satisfies the requested criteria.
+         *
+         * <p>Starting with {@link android.os.Build.VERSION_CODES#O} this method is guaranteed
+         * to be called immediately after {@link #onAvailable}.
+         *
+         * <p>Do NOT call {@link #getLinkProperties(Network)} or other synchronous
+         * ConnectivityManager methods in this callback as this is prone to race conditions :
+         * calling these methods while in a callback may return an outdated or even a null object.
          *
          * @param network The {@link Network} whose capabilities have changed.
          * @param networkCapabilities The new {@link android.net.NetworkCapabilities} for this
@@ -3321,8 +3363,14 @@
                 @NonNull NetworkCapabilities networkCapabilities) {}
 
         /**
-         * Called when the network the framework connected to for this request
-         * changes {@link LinkProperties}.
+         * Called when the network corresponding to this request changes {@link LinkProperties}.
+         *
+         * <p>Starting with {@link android.os.Build.VERSION_CODES#O} this method is guaranteed
+         * to be called immediately after {@link #onAvailable}.
+         *
+         * <p>Do NOT call {@link #getNetworkCapabilities(Network)} or other synchronous
+         * ConnectivityManager methods in this callback as this is prone to race conditions :
+         * calling these methods while in a callback may return an outdated or even a null object.
          *
          * @param network The {@link Network} whose link properties have changed.
          * @param linkProperties The new {@link LinkProperties} for this network.
@@ -3331,12 +3379,20 @@
                 @NonNull LinkProperties linkProperties) {}
 
         /**
-         * Called when the network the framework connected to for this request
-         * goes into {@link NetworkInfo.State#SUSPENDED}.
-         * This generally means that while the TCP connections are still live,
-         * temporarily network data fails to transfer.  Specifically this is used
-         * on cellular networks to mask temporary outages when driving through
-         * a tunnel, etc.
+         * Called when the network the framework connected to for this request suspends data
+         * transmission temporarily.
+         *
+         * <p>This generally means that while the TCP connections are still live temporarily
+         * network data fails to transfer. To give a specific example, this is used on cellular
+         * networks to mask temporary outages when driving through a tunnel, etc. In general this
+         * means read operations on sockets on this network will block once the buffers are
+         * drained, and write operations will block once the buffers are full.
+         *
+         * <p>Do NOT call {@link #getNetworkCapabilities(Network)} or
+         * {@link #getLinkProperties(Network)} or other synchronous ConnectivityManager methods in
+         * this callback as this is prone to race conditions (there is no guarantee the objects
+         * returned by these methods will be current).
+         *
          * @hide
          */
         public void onNetworkSuspended(@NonNull Network network) {}
@@ -3345,6 +3401,12 @@
          * Called when the network the framework connected to for this request
          * returns from a {@link NetworkInfo.State#SUSPENDED} state. This should always be
          * preceded by a matching {@link NetworkCallback#onNetworkSuspended} call.
+
+         * <p>Do NOT call {@link #getNetworkCapabilities(Network)} or
+         * {@link #getLinkProperties(Network)} or other synchronous ConnectivityManager methods in
+         * this callback as this is prone to race conditions : calling these methods while in a
+         * callback may return an outdated or even a null object.
+         *
          * @hide
          */
         public void onNetworkResumed(@NonNull Network network) {}
@@ -3352,6 +3414,11 @@
         /**
          * Called when access to the specified network is blocked or unblocked.
          *
+         * <p>Do NOT call {@link #getNetworkCapabilities(Network)} or
+         * {@link #getLinkProperties(Network)} or other synchronous ConnectivityManager methods in
+         * this callback as this is prone to race conditions : calling these methods while in a
+         * callback may return an outdated or even a null object.
+         *
          * @param network The {@link Network} whose blocked status has changed.
          * @param blocked The blocked status of this {@link Network}.
          */
@@ -3588,13 +3655,51 @@
     /**
      * Request a network to satisfy a set of {@link android.net.NetworkCapabilities}.
      *
-     * This {@link NetworkRequest} will live until released via
-     * {@link #unregisterNetworkCallback(NetworkCallback)} or the calling application exits. A
-     * version of the method which takes a timeout is
-     * {@link #requestNetwork(NetworkRequest, NetworkCallback, int)}.
-     * Status of the request can be followed by listening to the various
-     * callbacks described in {@link NetworkCallback}.  The {@link Network}
-     * can be used to direct traffic to the network.
+     * <p>This method will attempt to find the best network that matches the passed
+     * {@link NetworkRequest}, and to bring up one that does if none currently satisfies the
+     * criteria. The platform will evaluate which network is the best at its own discretion.
+     * Throughput, latency, cost per byte, policy, user preference and other considerations
+     * may be factored in the decision of what is considered the best network.
+     *
+     * <p>As long as this request is outstanding, the platform will try to maintain the best network
+     * matching this request, while always attempting to match the request to a better network if
+     * possible. If a better match is found, the platform will switch this request to the now-best
+     * network and inform the app of the newly best network by invoking
+     * {@link NetworkCallback#onAvailable(Network)} on the provided callback. Note that the platform
+     * will not try to maintain any other network than the best one currently matching the request:
+     * a network not matching any network request may be disconnected at any time.
+     *
+     * <p>For example, an application could use this method to obtain a connected cellular network
+     * even if the device currently has a data connection over Ethernet. This may cause the cellular
+     * radio to consume additional power. Or, an application could inform the system that it wants
+     * a network supporting sending MMSes and have the system let it know about the currently best
+     * MMS-supporting network through the provided {@link NetworkCallback}.
+     *
+     * <p>The status of the request can be followed by listening to the various callbacks described
+     * in {@link NetworkCallback}. The {@link Network} object passed to the callback methods can be
+     * used to direct traffic to the network (although accessing some networks may be subject to
+     * holding specific permissions). Callers will learn about the specific characteristics of the
+     * network through
+     * {@link NetworkCallback#onCapabilitiesChanged(Network, NetworkCapabilities)} and
+     * {@link NetworkCallback#onLinkPropertiesChanged(Network, LinkProperties)}. The methods of the
+     * provided {@link NetworkCallback} will only be invoked due to changes in the best network
+     * matching the request at any given time; therefore when a better network matching the request
+     * becomes available, the {@link NetworkCallback#onAvailable(Network)} method is called
+     * with the new network after which no further updates are given about the previously-best
+     * network, unless it becomes the best again at some later time. All callbacks are invoked
+     * in order on the same thread, which by default is a thread created by the framework running
+     * in the app.
+     * {@see #requestNetwork(NetworkRequest, NetworkCallback, Handler)} to change where the
+     * callbacks are invoked.
+     *
+     * <p>This{@link NetworkRequest} will live until released via
+     * {@link #unregisterNetworkCallback(NetworkCallback)} or the calling application exits, at
+     * which point the system may let go of the network at any time.
+     *
+     * <p>A version of this method which takes a timeout is
+     * {@link #requestNetwork(NetworkRequest, NetworkCallback, int)}, that an app can use to only
+     * wait for a limited amount of time for the network to become unavailable.
+     *
      * <p>It is presently unsupported to request a network with mutable
      * {@link NetworkCapabilities} such as
      * {@link NetworkCapabilities#NET_CAPABILITY_VALIDATED} or
@@ -3602,7 +3707,7 @@
      * as these {@code NetworkCapabilities} represent states that a particular
      * network may never attain, and whether a network will attain these states
      * is unknown prior to bringing up the network so the framework does not
-     * know how to go about satisfing a request with these capabilities.
+     * know how to go about satisfying a request with these capabilities.
      *
      * <p>This method requires the caller to hold either the
      * {@link android.Manifest.permission#CHANGE_NETWORK_STATE} permission
@@ -3625,34 +3730,17 @@
     /**
      * Request a network to satisfy a set of {@link android.net.NetworkCapabilities}.
      *
-     * This {@link NetworkRequest} will live until released via
-     * {@link #unregisterNetworkCallback(NetworkCallback)} or the calling application exits. A
-     * version of the method which takes a timeout is
-     * {@link #requestNetwork(NetworkRequest, NetworkCallback, int)}.
-     * Status of the request can be followed by listening to the various
-     * callbacks described in {@link NetworkCallback}.  The {@link Network}
-     * can be used to direct traffic to the network.
-     * <p>It is presently unsupported to request a network with mutable
-     * {@link NetworkCapabilities} such as
-     * {@link NetworkCapabilities#NET_CAPABILITY_VALIDATED} or
-     * {@link NetworkCapabilities#NET_CAPABILITY_CAPTIVE_PORTAL}
-     * as these {@code NetworkCapabilities} represent states that a particular
-     * network may never attain, and whether a network will attain these states
-     * is unknown prior to bringing up the network so the framework does not
-     * know how to go about satisfying a request with these capabilities.
+     * This method behaves identically to {@link #requestNetwork(NetworkRequest, NetworkCallback)}
+     * but runs all the callbacks on the passed Handler.
      *
-     * <p>This method requires the caller to hold either the
-     * {@link android.Manifest.permission#CHANGE_NETWORK_STATE} permission
-     * or the ability to modify system settings as determined by
-     * {@link android.provider.Settings.System#canWrite}.</p>
+     * <p>This method has the same permission requirements as
+     * {@link #requestNetwork(NetworkRequest, NetworkCallback)} and throws the same exceptions in
+     * the same conditions.
      *
      * @param request {@link NetworkRequest} describing this request.
      * @param networkCallback The {@link NetworkCallback} to be utilized for this request. Note
      *                        the callback must not be shared - it uniquely specifies this request.
      * @param handler {@link Handler} to specify the thread upon which the callback will be invoked.
-     * @throws IllegalArgumentException if {@code request} contains invalid network capabilities.
-     * @throws SecurityException if missing the appropriate permissions.
-     * @throws RuntimeException if request limit per UID is exceeded.
      */
     public void requestNetwork(@NonNull NetworkRequest request,
             @NonNull NetworkCallback networkCallback, @NonNull Handler handler) {
@@ -3677,10 +3765,9 @@
      * timeout) - {@link #registerNetworkCallback(NetworkRequest, NetworkCallback)} is provided
      * for that purpose. Calling this method will attempt to bring up the requested network.
      *
-     * <p>This method requires the caller to hold either the
-     * {@link android.Manifest.permission#CHANGE_NETWORK_STATE} permission
-     * or the ability to modify system settings as determined by
-     * {@link android.provider.Settings.System#canWrite}.</p>
+     * <p>This method has the same permission requirements as
+     * {@link #requestNetwork(NetworkRequest, NetworkCallback)} and throws the same exceptions in
+     * the same conditions.
      *
      * @param request {@link NetworkRequest} describing this request.
      * @param networkCallback The {@link NetworkCallback} to be utilized for this request. Note
@@ -3688,9 +3775,6 @@
      * @param timeoutMs The time in milliseconds to attempt looking for a suitable network
      *                  before {@link NetworkCallback#onUnavailable()} is called. The timeout must
      *                  be a positive value (i.e. >0).
-     * @throws IllegalArgumentException if {@code request} contains invalid network capabilities.
-     * @throws SecurityException if missing the appropriate permissions.
-     * @throws RuntimeException if request limit per UID is exceeded.
      */
     public void requestNetwork(@NonNull NetworkRequest request,
             @NonNull NetworkCallback networkCallback, int timeoutMs) {
@@ -3703,21 +3787,13 @@
      * Request a network to satisfy a set of {@link android.net.NetworkCapabilities}, limited
      * by a timeout.
      *
-     * This function behaves identically to the version without timeout, but if a suitable
-     * network is not found within the given time (in milliseconds) the
-     * {@link NetworkCallback#onUnavailable} callback is called. The request can still be
-     * released normally by calling {@link #unregisterNetworkCallback(NetworkCallback)} but does
-     * not have to be released if timed-out (it is automatically released). Unregistering a
-     * request that timed out is not an error.
+     * This method behaves identically to
+     * {@link #requestNetwork(NetworkRequest, NetworkCallback, int)} but runs all the callbacks
+     * on the passed Handler.
      *
-     * <p>Do not use this method to poll for the existence of specific networks (e.g. with a small
-     * timeout) - {@link #registerNetworkCallback(NetworkRequest, NetworkCallback)} is provided
-     * for that purpose. Calling this method will attempt to bring up the requested network.
-     *
-     * <p>This method requires the caller to hold either the
-     * {@link android.Manifest.permission#CHANGE_NETWORK_STATE} permission
-     * or the ability to modify system settings as determined by
-     * {@link android.provider.Settings.System#canWrite}.</p>
+     * <p>This method has the same permission requirements as
+     * {@link #requestNetwork(NetworkRequest, NetworkCallback, int)} and throws the same exceptions
+     * in the same conditions.
      *
      * @param request {@link NetworkRequest} describing this request.
      * @param networkCallback The {@link NetworkCallback} to be utilized for this request. Note
@@ -3725,9 +3801,6 @@
      * @param handler {@link Handler} to specify the thread upon which the callback will be invoked.
      * @param timeoutMs The time in milliseconds to attempt looking for a suitable network
      *                  before {@link NetworkCallback#onUnavailable} is called.
-     * @throws IllegalArgumentException if {@code request} contains invalid network capabilities.
-     * @throws SecurityException if missing the appropriate permissions.
-     * @throws RuntimeException if request limit per UID is exceeded.
      */
     public void requestNetwork(@NonNull NetworkRequest request,
             @NonNull NetworkCallback networkCallback, @NonNull Handler handler, int timeoutMs) {
diff --git a/core/java/android/net/LinkProperties.java b/core/java/android/net/LinkProperties.java
index d3f48ac..3ec0aea 100644
--- a/core/java/android/net/LinkProperties.java
+++ b/core/java/android/net/LinkProperties.java
@@ -68,6 +68,7 @@
     // in the format "rmem_min,rmem_def,rmem_max,wmem_min,wmem_def,wmem_max"
     private String mTcpBufferSizes;
     private IpPrefix mNat64Prefix;
+    private boolean mWakeOnLanSupported;
 
     private static final int MIN_MTU    = 68;
     private static final int MIN_MTU_V6 = 1280;
@@ -193,6 +194,7 @@
             setMtu(source.mMtu);
             mTcpBufferSizes = source.mTcpBufferSizes;
             mNat64Prefix = source.mNat64Prefix;
+            mWakeOnLanSupported = source.mWakeOnLanSupported;
         }
     }
 
@@ -852,6 +854,7 @@
         mMtu = 0;
         mTcpBufferSizes = null;
         mNat64Prefix = null;
+        mWakeOnLanSupported = false;
     }
 
     /**
@@ -913,6 +916,10 @@
         resultJoiner.add("MTU:");
         resultJoiner.add(Integer.toString(mMtu));
 
+        if (mWakeOnLanSupported) {
+            resultJoiner.add("WakeOnLanSupported: true");
+        }
+
         if (mTcpBufferSizes != null) {
             resultJoiner.add("TcpBufferSizes:");
             resultJoiner.add(mTcpBufferSizes);
@@ -1425,6 +1432,37 @@
     }
 
     /**
+     * Compares this {@code LinkProperties} WakeOnLan supported against the target.
+     *
+     * @param target LinkProperties to compare.
+     * @return {@code true} if both are identical, {@code false} otherwise.
+     * @hide
+     */
+    public boolean isIdenticalWakeOnLan(LinkProperties target) {
+        return isWakeOnLanSupported() == target.isWakeOnLanSupported();
+    }
+
+    /**
+     * Set whether the network interface supports WakeOnLAN
+     *
+     * @param supported WakeOnLAN supported value
+     *
+     * @hide
+     */
+    public void setWakeOnLanSupported(boolean supported) {
+        mWakeOnLanSupported = supported;
+    }
+
+    /**
+     * Returns whether the network interface supports WakeOnLAN
+     *
+     * @return {@code true} if interface supports WakeOnLAN, {@code false} otherwise.
+     */
+    public boolean isWakeOnLanSupported() {
+        return mWakeOnLanSupported;
+    }
+
+    /**
      * Compares this {@code LinkProperties} instance against the target
      * LinkProperties in {@code obj}. Two LinkPropertieses are equal if
      * all their fields are equal in values.
@@ -1461,7 +1499,8 @@
                 && isIdenticalStackedLinks(target)
                 && isIdenticalMtu(target)
                 && isIdenticalTcpBufferSizes(target)
-                && isIdenticalNat64Prefix(target);
+                && isIdenticalNat64Prefix(target)
+                && isIdenticalWakeOnLan(target);
     }
 
     /**
@@ -1577,7 +1616,8 @@
                 + (mUsePrivateDns ? 57 : 0)
                 + mPcscfs.size() * 67
                 + ((null == mPrivateDnsServerName) ? 0 : mPrivateDnsServerName.hashCode())
-                + Objects.hash(mNat64Prefix);
+                + Objects.hash(mNat64Prefix)
+                + (mWakeOnLanSupported ? 71 : 0);
     }
 
     /**
@@ -1622,6 +1662,8 @@
 
         ArrayList<LinkProperties> stackedLinks = new ArrayList<>(mStackedLinks.values());
         dest.writeList(stackedLinks);
+
+        dest.writeBoolean(mWakeOnLanSupported);
     }
 
     /**
@@ -1677,6 +1719,7 @@
                 for (LinkProperties stackedLink: stackedLinks) {
                     netProp.addStackedLink(stackedLink);
                 }
+                netProp.setWakeOnLanSupported(in.readBoolean());
                 return netProp;
             }
 
diff --git a/core/java/android/os/Build.java b/core/java/android/os/Build.java
index b3125d8..6a709b5 100755
--- a/core/java/android/os/Build.java
+++ b/core/java/android/os/Build.java
@@ -243,7 +243,8 @@
         public static final String BASE_OS = SystemProperties.get("ro.build.version.base_os", "");
 
         /**
-         * The user-visible security patch level.
+         * The user-visible security patch level. This value represents the date when the device
+         * most recently applied a security patch.
          */
         public static final String SECURITY_PATCH = SystemProperties.get(
                 "ro.build.version.security_patch", "");
diff --git a/core/java/android/os/Debug.java b/core/java/android/os/Debug.java
index 3cc2819..bc32df4 100644
--- a/core/java/android/os/Debug.java
+++ b/core/java/android/os/Debug.java
@@ -278,11 +278,13 @@
         /** @hide */
         public static final int OTHER_DALVIK_OTHER_ACCOUNTING = 22;
         /** @hide */
-        public static final int OTHER_DALVIK_OTHER_CODE_CACHE = 23;
+        public static final int OTHER_DALVIK_OTHER_ZYGOTE_CODE_CACHE = 23;
         /** @hide */
-        public static final int OTHER_DALVIK_OTHER_COMPILER_METADATA = 24;
+        public static final int OTHER_DALVIK_OTHER_APP_CODE_CACHE = 24;
         /** @hide */
-        public static final int OTHER_DALVIK_OTHER_INDIRECT_REFERENCE_TABLE = 25;
+        public static final int OTHER_DALVIK_OTHER_COMPILER_METADATA = 25;
+        /** @hide */
+        public static final int OTHER_DALVIK_OTHER_INDIRECT_REFERENCE_TABLE = 26;
         /** @hide */
         public static final int OTHER_DVK_STAT_DALVIK_OTHER_START =
                 OTHER_DALVIK_OTHER_LINEARALLOC - NUM_OTHER_STATS;
@@ -292,11 +294,11 @@
 
         // Dex subsections (Boot vdex, App dex, and App vdex).
         /** @hide */
-        public static final int OTHER_DEX_BOOT_VDEX = 26;
+        public static final int OTHER_DEX_BOOT_VDEX = 27;
         /** @hide */
-        public static final int OTHER_DEX_APP_DEX = 27;
+        public static final int OTHER_DEX_APP_DEX = 28;
         /** @hide */
-        public static final int OTHER_DEX_APP_VDEX = 28;
+        public static final int OTHER_DEX_APP_VDEX = 29;
         /** @hide */
         public static final int OTHER_DVK_STAT_DEX_START = OTHER_DEX_BOOT_VDEX - NUM_OTHER_STATS;
         /** @hide */
@@ -304,9 +306,9 @@
 
         // Art subsections (App image, boot image).
         /** @hide */
-        public static final int OTHER_ART_APP = 29;
+        public static final int OTHER_ART_APP = 30;
         /** @hide */
-        public static final int OTHER_ART_BOOT = 30;
+        public static final int OTHER_ART_BOOT = 31;
         /** @hide */
         public static final int OTHER_DVK_STAT_ART_START = OTHER_ART_APP - NUM_OTHER_STATS;
         /** @hide */
@@ -314,7 +316,7 @@
 
         /** @hide */
         @UnsupportedAppUsage
-        public static final int NUM_DVK_STATS = 14;
+        public static final int NUM_DVK_STATS = OTHER_ART_BOOT + 1 - OTHER_DALVIK_NORMAL;
 
         /** @hide */
         public static final int NUM_CATEGORIES = 9;
@@ -540,7 +542,8 @@
                 case OTHER_DALVIK_NON_MOVING: return ".NonMoving";
                 case OTHER_DALVIK_OTHER_LINEARALLOC: return ".LinearAlloc";
                 case OTHER_DALVIK_OTHER_ACCOUNTING: return ".GC";
-                case OTHER_DALVIK_OTHER_CODE_CACHE: return ".JITCache";
+                case OTHER_DALVIK_OTHER_ZYGOTE_CODE_CACHE: return ".ZygoteJIT";
+                case OTHER_DALVIK_OTHER_APP_CODE_CACHE: return ".AppJIT";
                 case OTHER_DALVIK_OTHER_COMPILER_METADATA: return ".CompilerMetadata";
                 case OTHER_DALVIK_OTHER_INDIRECT_REFERENCE_TABLE: return ".IndirectRef";
                 case OTHER_DEX_BOOT_VDEX: return ".Boot vdex";
@@ -722,7 +725,9 @@
               + getOtherPrivate(OTHER_APK)
               + getOtherPrivate(OTHER_TTF)
               + getOtherPrivate(OTHER_DEX)
-              + getOtherPrivate(OTHER_OAT);
+                + getOtherPrivate(OTHER_OAT)
+                + getOtherPrivate(OTHER_DALVIK_OTHER_ZYGOTE_CODE_CACHE)
+                + getOtherPrivate(OTHER_DALVIK_OTHER_APP_CODE_CACHE);
         }
 
         /**
@@ -813,7 +818,9 @@
                 + getOtherRss(OTHER_APK)
                 + getOtherRss(OTHER_TTF)
                 + getOtherRss(OTHER_DEX)
-                + getOtherRss(OTHER_OAT);
+                + getOtherRss(OTHER_OAT)
+                + getOtherRss(OTHER_DALVIK_OTHER_ZYGOTE_CODE_CACHE)
+                + getOtherRss(OTHER_DALVIK_OTHER_APP_CODE_CACHE);
         }
 
         /**
diff --git a/core/java/android/os/GraphicsEnvironment.java b/core/java/android/os/GraphicsEnvironment.java
index 7a70e93..947b0a1 100644
--- a/core/java/android/os/GraphicsEnvironment.java
+++ b/core/java/android/os/GraphicsEnvironment.java
@@ -69,6 +69,8 @@
     private static final String METADATA_DRIVER_BUILD_TIME = "com.android.gamedriver.build_time";
     private static final String METADATA_DEVELOPER_DRIVER_ENABLE =
             "com.android.graphics.developerdriver.enable";
+    private static final String METADATA_INJECT_LAYERS_ENABLE =
+            "com.android.graphics.injectLayers.enable";
     private static final String ANGLE_RULES_FILE = "a4a_rules.json";
     private static final String ANGLE_TEMP_RULES = "debug.angle.rules";
     private static final String ACTION_ANGLE_FOR_ANDROID = "android.app.action.ANGLE_FOR_ANDROID";
@@ -100,14 +102,16 @@
     public void setup(Context context, Bundle coreSettings) {
         final PackageManager pm = context.getPackageManager();
         final String packageName = context.getPackageName();
+        final ApplicationInfo appInfoWithMetaData =
+                getAppInfoWithMetadata(context, pm, packageName);
         Trace.traceBegin(Trace.TRACE_TAG_GRAPHICS, "setupGpuLayers");
-        setupGpuLayers(context, coreSettings, pm, packageName);
+        setupGpuLayers(context, coreSettings, pm, packageName, appInfoWithMetaData);
         Trace.traceEnd(Trace.TRACE_TAG_GRAPHICS);
         Trace.traceBegin(Trace.TRACE_TAG_GRAPHICS, "setupAngle");
         setupAngle(context, coreSettings, pm, packageName);
         Trace.traceEnd(Trace.TRACE_TAG_GRAPHICS);
         Trace.traceBegin(Trace.TRACE_TAG_GRAPHICS, "chooseDriver");
-        if (!chooseDriver(context, coreSettings, pm, packageName)) {
+        if (!chooseDriver(context, coreSettings, pm, packageName, appInfoWithMetaData)) {
             setGpuStats(SYSTEM_DRIVER_NAME, SYSTEM_DRIVER_VERSION_NAME, SYSTEM_DRIVER_VERSION_CODE,
                     SystemProperties.getLong(PROPERTY_GFX_DRIVER_BUILD_TIME, 0), packageName,
                     getVulkanVersion(pm));
@@ -180,6 +184,14 @@
     }
 
     /**
+     * Check whether application is has set the manifest metadata for layer injection.
+     */
+    private static boolean canInjectLayers(ApplicationInfo ai) {
+        return (ai.metaData != null && ai.metaData.getBoolean(METADATA_INJECT_LAYERS_ENABLE)
+                && setInjectLayersPrSetDumpable());
+    }
+
+    /**
      * Store the layer paths available to the loader.
      */
     public void setLayerPaths(ClassLoader classLoader,
@@ -225,15 +237,16 @@
      * If debuggable, check for additional debug settings
      */
     private void setupGpuLayers(
-            Context context, Bundle coreSettings, PackageManager pm, String packageName) {
+            Context context, Bundle coreSettings, PackageManager pm, String packageName,
+            ApplicationInfo ai) {
         String layerPaths = "";
 
         // Only enable additional debug functionality if the following conditions are met:
-        // 1. App is debuggable or device is rooted
+        // 1. App is debuggable or device is rooted or layer injection metadata flag is true
         // 2. ENABLE_GPU_DEBUG_LAYERS is true
         // 3. Package name is equal to GPU_DEBUG_APP
 
-        if (isDebuggable(context) || (getCanLoadSystemLibraries() == 1)) {
+        if (isDebuggable(context) || (getCanLoadSystemLibraries() == 1) || canInjectLayers(ai)) {
 
             final int enable = coreSettings.getInt(Settings.Global.ENABLE_GPU_DEBUG_LAYERS, 0);
 
@@ -343,6 +356,20 @@
         return -1;
     }
 
+    private static ApplicationInfo getAppInfoWithMetadata(Context context,
+                                                          PackageManager pm, String packageName) {
+        ApplicationInfo ai;
+        try {
+            // Get the ApplicationInfo from PackageManager so that metadata fields present.
+            ai = pm.getApplicationInfo(packageName, PackageManager.GET_META_DATA);
+        } catch (PackageManager.NameNotFoundException e) {
+            // Unlikely to fail for applications, but in case of failure, fall back to use the
+            // ApplicationInfo from context directly.
+            ai = context.getApplicationInfo();
+        }
+        return ai;
+    }
+
     private static String getDriverForPkg(Context context, Bundle bundle, String packageName) {
         final String allUseAngle;
         if (bundle != null) {
@@ -693,8 +720,7 @@
     /**
      * Return the driver package name to use. Return null for system driver.
      */
-    private static String chooseDriverInternal(
-            Context context, Bundle coreSettings, PackageManager pm, String packageName) {
+    private static String chooseDriverInternal(Bundle coreSettings, ApplicationInfo ai) {
         final String gameDriver = SystemProperties.get(PROPERTY_GFX_DRIVER);
         final boolean hasGameDriver = gameDriver != null && !gameDriver.isEmpty();
 
@@ -709,15 +735,6 @@
         // To minimize risk of driver updates crippling the device beyond user repair, never use an
         // updated driver for privileged or non-updated system apps. Presumably pre-installed apps
         // were tested thoroughly with the pre-installed driver.
-        ApplicationInfo ai;
-        try {
-            // Get the ApplicationInfo from PackageManager so that metadata fields present.
-            ai = pm.getApplicationInfo(packageName, PackageManager.GET_META_DATA);
-        } catch (PackageManager.NameNotFoundException e) {
-            // Unlikely to fail for applications, but in case of failure, fall back to use the
-            // ApplicationInfo from context directly.
-            ai = context.getApplicationInfo();
-        }
         if (ai.isPrivilegedApp() || (ai.isSystemApp() && !ai.isUpdatedSystemApp())) {
             if (DEBUG) Log.v(TAG, "Ignoring driver package for privileged/non-updated system app.");
             return null;
@@ -797,9 +814,9 @@
      * Choose whether the current process should use the builtin or an updated driver.
      */
     private static boolean chooseDriver(
-            Context context, Bundle coreSettings, PackageManager pm, String packageName) {
-        final String driverPackageName = chooseDriverInternal(context, coreSettings, pm,
-                packageName);
+            Context context, Bundle coreSettings, PackageManager pm, String packageName,
+            ApplicationInfo ai) {
+        final String driverPackageName = chooseDriverInternal(coreSettings, ai);
         if (driverPackageName == null) {
             return false;
         }
@@ -911,4 +928,5 @@
     private static native void setAngleInfo(String path, String appPackage, String devOptIn,
             FileDescriptor rulesFd, long rulesOffset, long rulesLength);
     private static native boolean getShouldUseAngle(String packageName);
+    private static native boolean setInjectLayersPrSetDumpable();
 }
diff --git a/core/java/android/os/HwParcel.java b/core/java/android/os/HwParcel.java
index cfb582e..5e8929c 100644
--- a/core/java/android/os/HwParcel.java
+++ b/core/java/android/os/HwParcel.java
@@ -23,6 +23,8 @@
 import android.annotation.TestApi;
 import android.annotation.UnsupportedAppUsage;
 
+import dalvik.annotation.optimization.FastNative;
+
 import libcore.util.NativeAllocationRegistry;
 
 import java.lang.annotation.Retention;
@@ -72,46 +74,54 @@
 
     /**
      * Writes an interface token into the parcel used to verify that
-     * a transaction has made it to the write type of interface.
+     * a transaction has made it to the right type of interface.
      *
      * @param interfaceName fully qualified name of interface message
      *     is being sent to.
      */
+    @FastNative
     public native final void writeInterfaceToken(String interfaceName);
     /**
      * Writes a boolean value to the end of the parcel.
      * @param val to write
      */
+    @FastNative
     public native final void writeBool(boolean val);
     /**
      * Writes a byte value to the end of the parcel.
      * @param val to write
      */
+    @FastNative
     public native final void writeInt8(byte val);
     /**
      * Writes a short value to the end of the parcel.
      * @param val to write
      */
+    @FastNative
     public native final void writeInt16(short val);
     /**
      * Writes a int value to the end of the parcel.
      * @param val to write
      */
+    @FastNative
     public native final void writeInt32(int val);
     /**
      * Writes a long value to the end of the parcel.
      * @param val to write
      */
+    @FastNative
     public native final void writeInt64(long val);
     /**
      * Writes a float value to the end of the parcel.
      * @param val to write
      */
+    @FastNative
     public native final void writeFloat(float val);
     /**
      * Writes a double value to the end of the parcel.
      * @param val to write
      */
+    @FastNative
     public native final void writeDouble(double val);
     /**
      * Writes a String value to the end of the parcel.
@@ -120,6 +130,7 @@
      *
      * @param val to write
      */
+    @FastNative
     public native final void writeString(String val);
     /**
      * Writes a native handle (without duplicating the underlying
@@ -127,42 +138,50 @@
      *
      * @param val to write
      */
+    @FastNative
     public native final void writeNativeHandle(@Nullable NativeHandle val);
 
     /**
      * Writes an array of boolean values to the end of the parcel.
      * @param val to write
      */
+    @FastNative
     private native final void writeBoolVector(boolean[] val);
     /**
      * Writes an array of byte values to the end of the parcel.
      * @param val to write
      */
+    @FastNative
     private native final void writeInt8Vector(byte[] val);
     /**
      * Writes an array of short values to the end of the parcel.
      * @param val to write
      */
+    @FastNative
     private native final void writeInt16Vector(short[] val);
     /**
      * Writes an array of int values to the end of the parcel.
      * @param val to write
      */
+    @FastNative
     private native final void writeInt32Vector(int[] val);
     /**
      * Writes an array of long values to the end of the parcel.
      * @param val to write
      */
+    @FastNative
     private native final void writeInt64Vector(long[] val);
     /**
      * Writes an array of float values to the end of the parcel.
      * @param val to write
      */
+    @FastNative
     private native final void writeFloatVector(float[] val);
     /**
      * Writes an array of double values to the end of the parcel.
      * @param val to write
      */
+    @FastNative
     private native final void writeDoubleVector(double[] val);
     /**
      * Writes an array of String values to the end of the parcel.
@@ -171,6 +190,7 @@
      *
      * @param val to write
      */
+    @FastNative
     private native final void writeStringVector(String[] val);
     /**
      * Writes an array of native handles to the end of the parcel.
@@ -179,6 +199,7 @@
      *
      * @param val array of {@link NativeHandle} objects to write
      */
+    @FastNative
     private native final void writeNativeHandleVector(NativeHandle[] val);
 
     /**
@@ -299,6 +320,7 @@
      * Write a hwbinder object to the end of the parcel.
      * @param binder value to write
      */
+    @FastNative
     public native final void writeStrongBinder(IHwBinder binder);
 
     /**
@@ -314,48 +336,56 @@
      * @return value parsed from the parcel
      * @throws IllegalArgumentException if the parcel has no more data
      */
+    @FastNative
     public native final boolean readBool();
     /**
      * Reads a byte value from the current location in the parcel.
      * @return value parsed from the parcel
      * @throws IllegalArgumentException if the parcel has no more data
      */
+    @FastNative
     public native final byte readInt8();
     /**
      * Reads a short value from the current location in the parcel.
      * @return value parsed from the parcel
      * @throws IllegalArgumentException if the parcel has no more data
      */
+    @FastNative
     public native final short readInt16();
     /**
      * Reads a int value from the current location in the parcel.
      * @return value parsed from the parcel
      * @throws IllegalArgumentException if the parcel has no more data
      */
+    @FastNative
     public native final int readInt32();
     /**
      * Reads a long value from the current location in the parcel.
      * @return value parsed from the parcel
      * @throws IllegalArgumentException if the parcel has no more data
      */
+    @FastNative
     public native final long readInt64();
     /**
      * Reads a float value from the current location in the parcel.
      * @return value parsed from the parcel
      * @throws IllegalArgumentException if the parcel has no more data
      */
+    @FastNative
     public native final float readFloat();
     /**
      * Reads a double value from the current location in the parcel.
      * @return value parsed from the parcel
      * @throws IllegalArgumentException if the parcel has no more data
      */
+    @FastNative
     public native final double readDouble();
     /**
      * Reads a String value from the current location in the parcel.
      * @return value parsed from the parcel
      * @throws IllegalArgumentException if the parcel has no more data
      */
+    @FastNative
     public native final String readString();
     /**
      * Reads a native handle (without duplicating the underlying file
@@ -366,6 +396,7 @@
      * @return a {@link NativeHandle} instance parsed from the parcel
      * @throws IllegalArgumentException if the parcel has no more data
      */
+    @FastNative
     public native final @Nullable NativeHandle readNativeHandle();
     /**
      * Reads an embedded native handle (without duplicating the underlying
@@ -379,6 +410,7 @@
      * @return a {@link NativeHandle} instance parsed from the parcel
      * @throws IllegalArgumentException if the parcel has no more data
      */
+    @FastNative
     public native final @Nullable NativeHandle readEmbeddedNativeHandle(
             long parentHandle, long offset);
 
@@ -387,54 +419,63 @@
      * @return array of parsed values
      * @throws IllegalArgumentException if the parcel has no more data
      */
+    @FastNative
     private native final boolean[] readBoolVectorAsArray();
     /**
      * Reads an array of byte values from the parcel.
      * @return array of parsed values
      * @throws IllegalArgumentException if the parcel has no more data
      */
+    @FastNative
     private native final byte[] readInt8VectorAsArray();
     /**
      * Reads an array of short values from the parcel.
      * @return array of parsed values
      * @throws IllegalArgumentException if the parcel has no more data
      */
+    @FastNative
     private native final short[] readInt16VectorAsArray();
     /**
      * Reads an array of int values from the parcel.
      * @return array of parsed values
      * @throws IllegalArgumentException if the parcel has no more data
      */
+    @FastNative
     private native final int[] readInt32VectorAsArray();
     /**
      * Reads an array of long values from the parcel.
      * @return array of parsed values
      * @throws IllegalArgumentException if the parcel has no more data
      */
+    @FastNative
     private native final long[] readInt64VectorAsArray();
     /**
      * Reads an array of float values from the parcel.
      * @return array of parsed values
      * @throws IllegalArgumentException if the parcel has no more data
      */
+    @FastNative
     private native final float[] readFloatVectorAsArray();
     /**
      * Reads an array of double values from the parcel.
      * @return array of parsed values
      * @throws IllegalArgumentException if the parcel has no more data
      */
+    @FastNative
     private native final double[] readDoubleVectorAsArray();
     /**
      * Reads an array of String values from the parcel.
      * @return array of parsed values
      * @throws IllegalArgumentException if the parcel has no more data
      */
+    @FastNative
     private native final String[] readStringVectorAsArray();
     /**
      * Reads an array of native handles from the parcel.
      * @return array of {@link NativeHandle} objects
      * @throws IllegalArgumentException if the parcel has no more data
      */
+    @FastNative
     private native final NativeHandle[] readNativeHandleAsArray();
 
     /**
@@ -537,6 +578,7 @@
      * @return binder object read from parcel or null if no binder can be read
      * @throws IllegalArgumentException if the parcel has no more data
      */
+    @FastNative
     public native final IHwBinder readStrongBinder();
 
     /**
@@ -544,6 +586,7 @@
      * @return blob of size expectedSize
      * @throws IllegalArgumentException if the parcel has no more data
      */
+    @FastNative
     public native final HwBlob readBuffer(long expectedSize);
 
     /**
@@ -559,6 +602,7 @@
      * @throws NullPointerException if the transaction specified the blob to be null
      *    but nullable is false
      */
+    @FastNative
     public native final HwBlob readEmbeddedBuffer(
             long expectedSize, long parentHandle, long offset,
             boolean nullable);
@@ -567,26 +611,31 @@
      * Write a buffer into the transaction.
      * @param blob blob to write into the parcel.
      */
+    @FastNative
     public native final void writeBuffer(HwBlob blob);
     /**
      * Write a status value into the blob.
      * @param status value to write
      */
+    @FastNative
     public native final void writeStatus(int status);
     /**
      * @throws IllegalArgumentException if a success vaue cannot be read
      * @throws RemoteException if success value indicates a transaction error
      */
+    @FastNative
     public native final void verifySuccess();
     /**
      * Should be called to reduce memory pressure when this object no longer needs
      * to be written to.
      */
+    @FastNative
     public native final void releaseTemporaryStorage();
     /**
      * Should be called when object is no longer needed to reduce possible memory
      * pressure if the Java GC does not get to this object in time.
      */
+    @FastNative
     public native final void release();
 
     /**
@@ -597,6 +646,7 @@
     // Returns address of the "freeFunction".
     private static native final long native_init();
 
+    @FastNative
     private native final void native_setup(boolean allocate);
 
     static {
diff --git a/core/java/android/os/IUserManager.aidl b/core/java/android/os/IUserManager.aidl
index 63641e5..c30491a 100644
--- a/core/java/android/os/IUserManager.aidl
+++ b/core/java/android/os/IUserManager.aidl
@@ -41,6 +41,7 @@
      */
 
     UserInfo createUser(in String name, int flags);
+    UserInfo preCreateUser(int flags);
     UserInfo createProfileForUser(in String name, int flags, int userHandle,
             in String[] disallowedPackages);
     UserInfo createRestrictedProfile(String name, int parentUserHandle);
@@ -53,7 +54,7 @@
     void setUserIcon(int userHandle, in Bitmap icon);
     ParcelFileDescriptor getUserIcon(int userHandle);
     UserInfo getPrimaryUser();
-    List<UserInfo> getUsers(boolean excludeDying);
+    List<UserInfo> getUsers(boolean excludePartial, boolean excludeDying, boolean excludePreCreated);
     List<UserInfo> getProfiles(int userHandle, boolean enabledOnly);
     int[] getProfileIds(int userId, boolean enabledOnly);
     boolean canAddMoreManagedProfiles(int userHandle, boolean allowedToRemoveOne);
@@ -92,6 +93,7 @@
     boolean someUserHasSeedAccount(in String accountName, in String accountType);
     boolean isManagedProfile(int userId);
     boolean isDemoUser(int userId);
+    boolean isPreCreated(int userId);
     UserInfo createProfileForUserEvenWhenDisallowed(in String name, int flags, int userHandle,
             in String[] disallowedPackages);
     boolean isUserUnlockingOrUnlocked(int userId);
diff --git a/core/java/android/os/OWNERS b/core/java/android/os/OWNERS
index b568f15..e371df0 100644
--- a/core/java/android/os/OWNERS
+++ b/core/java/android/os/OWNERS
@@ -1,2 +1,4 @@
 # Zygote
 per-file ZygoteProcess.java = chriswailes@google.com, ngeoffray@google.com, sehr@google.com, narayan@google.com, maco@google.com
+
+per-file GraphicsEnvironment.java = chrisforbes@google.com, cnorthrop@google.com, lpy@google.com, timvp@google.com, zzyiwei@google.com
diff --git a/core/java/android/os/Parcel.java b/core/java/android/os/Parcel.java
index 50487e9..783ab44 100644
--- a/core/java/android/os/Parcel.java
+++ b/core/java/android/os/Parcel.java
@@ -305,8 +305,11 @@
     private static native void nativeWriteFloat(long nativePtr, float val);
     @FastNative
     private static native void nativeWriteDouble(long nativePtr, double val);
+    @FastNative
     static native void nativeWriteString(long nativePtr, String val);
+    @FastNative
     private static native void nativeWriteStrongBinder(long nativePtr, IBinder val);
+    @FastNative
     private static native long nativeWriteFileDescriptor(long nativePtr, FileDescriptor val);
 
     private static native byte[] nativeCreateByteArray(long nativePtr);
@@ -320,8 +323,11 @@
     private static native float nativeReadFloat(long nativePtr);
     @CriticalNative
     private static native double nativeReadDouble(long nativePtr);
+    @FastNative
     static native String nativeReadString(long nativePtr);
+    @FastNative
     private static native IBinder nativeReadStrongBinder(long nativePtr);
+    @FastNative
     private static native FileDescriptor nativeReadFileDescriptor(long nativePtr);
 
     private static native long nativeCreate();
diff --git a/core/java/android/os/ParcelFileDescriptor.java b/core/java/android/os/ParcelFileDescriptor.java
index bcb94ce..fdb44e7 100644
--- a/core/java/android/os/ParcelFileDescriptor.java
+++ b/core/java/android/os/ParcelFileDescriptor.java
@@ -35,12 +35,15 @@
 import android.annotation.UnsupportedAppUsage;
 import android.content.BroadcastReceiver;
 import android.content.ContentProvider;
+import android.content.ContentResolver;
+import android.net.Uri;
 import android.os.MessageQueue.OnFileDescriptorEventListener;
 import android.system.ErrnoException;
 import android.system.Os;
 import android.system.OsConstants;
 import android.system.StructStat;
 import android.util.Log;
+import android.util.Size;
 
 import dalvik.system.CloseGuard;
 import dalvik.system.VMRuntime;
@@ -204,6 +207,10 @@
 
     /**
      * Create a new ParcelFileDescriptor accessing a given file.
+     * <p>
+     * This method should only be used for files that you have direct access to;
+     * if you'd like to work with files hosted outside your app, use an API like
+     * {@link ContentResolver#openFile(Uri, String, CancellationSignal)}.
      *
      * @param file The file to be opened.
      * @param mode The desired access mode, must be one of
@@ -226,6 +233,10 @@
 
     /**
      * Create a new ParcelFileDescriptor accessing a given file.
+     * <p>
+     * This method should only be used for files that you have direct access to;
+     * if you'd like to work with files hosted outside your app, use an API like
+     * {@link ContentResolver#openFile(Uri, String, CancellationSignal)}.
      *
      * @param file The file to be opened.
      * @param mode The desired access mode, must be one of
diff --git a/core/java/android/os/Process.java b/core/java/android/os/Process.java
index 76e728a..43b9c67 100644
--- a/core/java/android/os/Process.java
+++ b/core/java/android/os/Process.java
@@ -420,10 +420,9 @@
      * Background thread group - All threads in
      * this group are scheduled with a reduced share of the CPU.
      * Value is same as constant SP_BACKGROUND of enum SchedPolicy.
-     * FIXME rename to THREAD_GROUP_BACKGROUND.
      * @hide
      */
-    public static final int THREAD_GROUP_BG_NONINTERACTIVE = 0;
+    public static final int THREAD_GROUP_BACKGROUND = 0;
 
     /**
      * Foreground thread group - All threads in
@@ -809,7 +808,7 @@
      *
      * group == THREAD_GROUP_DEFAULT means to move all non-background priority
      * threads to the foreground scheduling group, but to leave background
-     * priority threads alone.  group == THREAD_GROUP_BG_NONINTERACTIVE moves all
+     * priority threads alone.  group == THREAD_GROUP_BACKGROUND moves all
      * threads, regardless of priority, to the background scheduling group.
      * group == THREAD_GROUP_FOREGROUND is not allowed.
      *
diff --git a/core/java/android/os/UpdateEngine.java b/core/java/android/os/UpdateEngine.java
index dd5e20e..a9ddffe 100644
--- a/core/java/android/os/UpdateEngine.java
+++ b/core/java/android/os/UpdateEngine.java
@@ -22,8 +22,6 @@
 import android.os.IUpdateEngineCallback;
 import android.os.RemoteException;
 
-import java.io.FileDescriptor;
-
 /**
  * UpdateEngine handles calls to the update engine which takes care of A/B OTA
  * updates. It wraps up the update engine Binder APIs and exposes them as
@@ -315,16 +313,16 @@
     }
 
     /**
-     * Applies the payload passed as file descriptor {@code fd} instead of
+     * Applies the payload passed as ParcelFileDescriptor {@code pfd} instead of
      * using the {@code file://} scheme.
      *
      * <p>See {@link #applyPayload(String)} for {@code offset}, {@code size} and
      * {@code headerKeyValuePairs} parameters.
      */
-    public void applyPayload(@NonNull FileDescriptor fd, long offset, long size,
+    public void applyPayload(@NonNull ParcelFileDescriptor pfd, long offset, long size,
             @NonNull String[] headerKeyValuePairs) {
         try {
-            mUpdateEngine.applyPayloadFd(fd, offset, size, headerKeyValuePairs);
+            mUpdateEngine.applyPayloadFd(pfd, offset, size, headerKeyValuePairs);
         } catch (RemoteException e) {
             throw e.rethrowFromSystemServer();
         }
diff --git a/core/java/android/os/UserHandle.java b/core/java/android/os/UserHandle.java
index 0754dc7..3558fcd 100644
--- a/core/java/android/os/UserHandle.java
+++ b/core/java/android/os/UserHandle.java
@@ -39,6 +39,7 @@
 
     /** @hide A user id to indicate all users on the device */
     @UnsupportedAppUsage
+    @TestApi
     public static final @UserIdInt int USER_ALL = -1;
 
     /** @hide A user handle to indicate all users on the device */
@@ -69,8 +70,11 @@
 
     /** @hide An undefined user id */
     @UnsupportedAppUsage
+    @TestApi
     public static final @UserIdInt int USER_NULL = -10000;
 
+    private static final @NonNull UserHandle NULL = new UserHandle(USER_NULL);
+
     /**
      * @hide A user id constant to indicate the "owner" user of the device
      * @deprecated Consider using either {@link UserHandle#USER_SYSTEM} constant or
@@ -91,6 +95,7 @@
 
     /** @hide A user id constant to indicate the "system" user of the device */
     @UnsupportedAppUsage
+    @TestApi
     public static final @UserIdInt int USER_SYSTEM = 0;
 
     /** @hide A user serial constant to indicate the "system" user of the device */
@@ -110,6 +115,27 @@
     public static final boolean MU_ENABLED = true;
 
     /** @hide */
+    @TestApi
+    public static final int MIN_SECONDARY_USER_ID = 10;
+
+    /**
+     * Arbitrary user handle cache size. We use the cache even when {@link #MU_ENABLED} is false
+     * anyway, so we can always assume in CTS that UserHandle.of(10) returns a cached instance
+     * even on non-multiuser devices.
+     */
+    private static final int NUM_CACHED_USERS = 4;
+
+    private static final UserHandle[] CACHED_USER_INFOS = new UserHandle[NUM_CACHED_USERS];
+
+    static {
+        // Not lazily initializing the cache, so that we can share them across processes.
+        // (We'll create them in zygote.)
+        for (int i = 0; i < CACHED_USER_INFOS.length; i++) {
+            CACHED_USER_INFOS[i] = new UserHandle(MIN_SECONDARY_USER_ID + i);
+        }
+    }
+
+    /** @hide */
     @UnsupportedAppUsage
     public static final int ERR_GID = -1;
     /** @hide */
@@ -209,6 +235,7 @@
      * @hide
      */
     @UnsupportedAppUsage
+    @TestApi
     public static @UserIdInt int getUserId(int uid) {
         if (MU_ENABLED) {
             return uid / PER_USER_RANGE;
@@ -229,9 +256,31 @@
     }
 
     /** @hide */
+    @TestApi
     @SystemApi
     public static UserHandle of(@UserIdInt int userId) {
-        return userId == USER_SYSTEM ? SYSTEM : new UserHandle(userId);
+        if (userId == USER_SYSTEM) {
+            return SYSTEM; // Most common.
+        }
+        // These are sequential; so use a switch. Maybe they'll be optimized to a table lookup.
+        switch (userId) {
+            case USER_ALL:
+                return ALL;
+
+            case USER_CURRENT:
+                return CURRENT;
+
+            case USER_CURRENT_OR_SELF:
+                return CURRENT_OR_SELF;
+        }
+        if (userId >= MIN_SECONDARY_USER_ID
+                && userId < (MIN_SECONDARY_USER_ID + CACHED_USER_INFOS.length)) {
+            return CACHED_USER_INFOS[userId - MIN_SECONDARY_USER_ID];
+        }
+        if (userId == USER_NULL) { // Not common.
+            return NULL;
+        }
+        return new UserHandle(userId);
     }
 
     /**
@@ -239,6 +288,7 @@
      * @hide
      */
     @UnsupportedAppUsage
+    @TestApi
     public static int getUid(@UserIdInt int userId, @AppIdInt int appId) {
         if (MU_ENABLED) {
             return userId * PER_USER_RANGE + (appId % PER_USER_RANGE);
@@ -404,6 +454,7 @@
      * @hide
      */
     @SystemApi
+    @TestApi
     public static @UserIdInt int myUserId() {
         return getUserId(Process.myUid());
     }
@@ -513,7 +564,9 @@
     public static final @android.annotation.NonNull Parcelable.Creator<UserHandle> CREATOR
             = new Parcelable.Creator<UserHandle>() {
         public UserHandle createFromParcel(Parcel in) {
-            return new UserHandle(in);
+            // Try to avoid allocation; use of() here. Keep this and the constructor below
+            // in sync.
+            return UserHandle.of(in.readInt());
         }
 
         public UserHandle[] newArray(int size) {
@@ -532,6 +585,6 @@
      * positioned at the location in the buffer where it was written.
      */
     public UserHandle(Parcel in) {
-        mHandle = in.readInt();
+        mHandle = in.readInt(); // Keep this and createFromParcel() in sync.
     }
 }
diff --git a/core/java/android/os/UserManager.java b/core/java/android/os/UserManager.java
index af574da..3296f11 100644
--- a/core/java/android/os/UserManager.java
+++ b/core/java/android/os/UserManager.java
@@ -37,6 +37,7 @@
 import android.content.IntentFilter;
 import android.content.IntentSender;
 import android.content.pm.UserInfo;
+import android.content.pm.UserInfo.UserInfoFlag;
 import android.content.res.Configuration;
 import android.content.res.Resources;
 import android.graphics.Bitmap;
@@ -2013,18 +2014,20 @@
 
     /**
      * Creates a user with the specified name and options. For non-admin users, default user
-     * restrictions are going to be applied.
-     * Requires {@link android.Manifest.permission#MANAGE_USERS} permission.
+     * restrictions will be applied.
+     *
+     * <p>Requires {@link android.Manifest.permission#MANAGE_USERS} permission.
      *
      * @param name the user's name
-     * @param flags flags that identify the type of user and other properties.
+     * @param flags UserInfo flags that identify the type of user and other properties.
      * @see UserInfo
      *
-     * @return the UserInfo object for the created user, or null if the user could not be created.
+     * @return the UserInfo object for the created user, or {@code null} if the user could not be
+     * created.
      * @hide
      */
     @UnsupportedAppUsage
-    public UserInfo createUser(String name, int flags) {
+    public @Nullable UserInfo createUser(@Nullable String name, @UserInfoFlag int flags) {
         UserInfo user = null;
         try {
             user = mService.createUser(name, flags);
@@ -2041,6 +2044,36 @@
     }
 
     /**
+     * Pre-creates a user with the specified name and options. For non-admin users, default user
+     * restrictions will be applied.
+     *
+     * <p>This method can be used by OEMs to "warm" up the user creation by pre-creating some users
+     * at the first boot, so they when the "real" user is created (for example,
+     * by {@link #createUser(String, int)} or {@link #createGuest(Context, String)}), it takes
+     * less time.
+     *
+     * <p>Requires {@link android.Manifest.permission#MANAGE_USERS} permission.
+     *
+     * @param flags UserInfo flags that identify the type of user and other properties.
+     * @see UserInfo
+     *
+     * @return the UserInfo object for the created user, or {@code null} if the user could not be
+     * created.
+     *
+     * @throw {@link IllegalArgumentException} if {@code flags} contains
+     * {@link UserInfo#FLAG_MANAGED_PROFILE}.
+     *
+     * @hide
+     */
+    public @Nullable UserInfo preCreateUser(@UserInfoFlag int flags) {
+        try {
+            return mService.preCreateUser(flags);
+        } catch (RemoteException re) {
+            throw re.rethrowFromSystemServer();
+        }
+    }
+
+    /**
      * Creates a guest user and configures it.
      * @param context an application context
      * @param name the name to set for the user
@@ -2356,15 +2389,26 @@
     /**
      * Returns information for all users on this device, including ones marked for deletion.
      * To retrieve only users that are alive, use {@link #getUsers(boolean)}.
-     * <p>
-     * Requires {@link android.Manifest.permission#MANAGE_USERS} permission.
+     *
      * @return the list of users that exist on the device.
      * @hide
      */
     @UnsupportedAppUsage
+    @RequiresPermission(android.Manifest.permission.MANAGE_USERS)
     public List<UserInfo> getUsers() {
+        return getUsers(/* excludeDying= */ false);
+    }
+
+    /**
+     * Returns information for all users on this device, based on the filtering parameters.
+     *
+     * @hide
+     */
+    @RequiresPermission(android.Manifest.permission.MANAGE_USERS)
+    public List<UserInfo> getUsers(boolean excludePartial, boolean excludeDying,
+            boolean excludePreCreated) {
         try {
-            return mService.getUsers(false);
+            return mService.getUsers(excludePartial, excludeDying, excludePreCreated);
         } catch (RemoteException re) {
             throw re.rethrowFromSystemServer();
         }
@@ -2380,16 +2424,12 @@
     @SystemApi
     @RequiresPermission(android.Manifest.permission.MANAGE_USERS)
     public long[] getSerialNumbersOfUsers(boolean excludeDying) {
-        try {
-            List<UserInfo> users = mService.getUsers(excludeDying);
-            long[] result = new long[users.size()];
-            for (int i = 0; i < result.length; i++) {
-                result[i] = users.get(i).serialNumber;
-            }
-            return result;
-        } catch (RemoteException re) {
-            throw re.rethrowFromSystemServer();
+        List<UserInfo> users = getUsers(excludeDying);
+        long[] result = new long[users.size()];
+        for (int i = 0; i < result.length; i++) {
+            result[i] = users.get(i).serialNumber;
         }
+        return result;
     }
 
     /**
@@ -2773,11 +2813,8 @@
      */
     @UnsupportedAppUsage
     public @NonNull List<UserInfo> getUsers(boolean excludeDying) {
-        try {
-            return mService.getUsers(excludeDying);
-        } catch (RemoteException re) {
-            throw re.rethrowFromSystemServer();
-        }
+        return getUsers(/*excludePartial= */ true, excludeDying,
+                /* excludePreCreated= */ true);
     }
 
     /**
diff --git a/core/java/android/os/ZygoteProcess.java b/core/java/android/os/ZygoteProcess.java
index 9a3a7ce..907eae8 100644
--- a/core/java/android/os/ZygoteProcess.java
+++ b/core/java/android/os/ZygoteProcess.java
@@ -758,6 +758,7 @@
                 ZygoteState state = openZygoteSocketIfNeeded(abi);
                 state.mZygoteOutputWriter.write("1\n--boot-completed\n");
                 state.mZygoteOutputWriter.flush();
+                state.mZygoteInputStream.readInt();
             }
         } catch (Exception ex) {
             throw new RuntimeException("Failed to inform zygote of boot_completed", ex);
diff --git a/core/java/android/os/telephony/TelephonyRegistryManager.java b/core/java/android/os/telephony/TelephonyRegistryManager.java
index 5c49cb6..1332331 100644
--- a/core/java/android/os/telephony/TelephonyRegistryManager.java
+++ b/core/java/android/os/telephony/TelephonyRegistryManager.java
@@ -21,13 +21,13 @@
 import android.os.Bundle;
 import android.os.RemoteException;
 import android.os.ServiceManager;
-import android.telephony.Annotation;
 import android.telephony.Annotation.ApnType;
 import android.telephony.Annotation.CallState;
 import android.telephony.Annotation.DataActivityType;
 import android.telephony.Annotation.DataFailureCause;
 import android.telephony.Annotation.DataState;
 import android.telephony.Annotation.NetworkType;
+import android.telephony.Annotation.PreciseCallStates;
 import android.telephony.Annotation.RadioPowerState;
 import android.telephony.Annotation.SimActivationState;
 import android.telephony.Annotation.SrvccState;
@@ -35,7 +35,6 @@
 import android.telephony.CellInfo;
 import android.telephony.DisconnectCause;
 import android.telephony.PhoneCapability;
-import android.telephony.PreciseCallState.State;
 import android.telephony.ServiceState;
 import android.telephony.SignalStrength;
 import android.telephony.TelephonyManager;
@@ -466,8 +465,10 @@
      *
      * @hide
      */
-    public void notifyPreciseCallState(int subId, int slotIndex, @State int ringCallPreciseState,
-        @State int foregroundCallPreciseState, @State int backgroundCallPreciseState) {
+    public void notifyPreciseCallState(int subId, int slotIndex,
+        @PreciseCallStates int ringCallPreciseState,
+        @PreciseCallStates int foregroundCallPreciseState,
+        @PreciseCallStates int backgroundCallPreciseState) {
         try {
             sRegistry.notifyPreciseCallState(slotIndex, subId, ringCallPreciseState,
                 foregroundCallPreciseState, backgroundCallPreciseState);
diff --git a/core/java/android/provider/DeviceConfig.java b/core/java/android/provider/DeviceConfig.java
index fd1381a..e456c8a 100644
--- a/core/java/android/provider/DeviceConfig.java
+++ b/core/java/android/provider/DeviceConfig.java
@@ -403,9 +403,37 @@
     @TestApi
     @RequiresPermission(READ_DEVICE_CONFIG)
     public static String getProperty(@NonNull String namespace, @NonNull String name) {
+        // Fetch all properties for the namespace at once and cache them in the local process, so we
+        // incur the cost of the IPC less often. Lookups happen much more frequently than updates,
+        // and we want to optimize the former.
+        return getProperties(namespace, name).getString(name, null);
+    }
+
+    /**
+     * Look up the values of multiple properties for a particular namespace. The lookup is atomic,
+     * such that the values of these properties cannot change between the time when the first is
+     * fetched and the time when the last is fetched.
+     *
+     * TODO: reference setProperties when it is added.
+     *
+     * @param namespace The namespace containing the properties to look up.
+     * @param names     The names of properties to look up, or empty to fetch all properties for the
+     *                  given namespace.
+     * @return {@link Properties} object containing the requested properties. This reflects the
+     *     state of these properties at the time of the lookup, and is not updated to reflect any
+     *     future changes. The keyset of this Properties object will contain only the intersection
+     *     of properties already set and properties requested via the names parameter. Properties
+     *     that are already set but were not requested will not be contained here. Properties that
+     *     are not set, but were requested will not be contained here either.
+     * @hide
+     */
+    @SystemApi
+    @NonNull
+    @RequiresPermission(READ_DEVICE_CONFIG)
+    public static Properties getProperties(@NonNull String namespace, @NonNull String ... names) {
         ContentResolver contentResolver = ActivityThread.currentApplication().getContentResolver();
-        String compositeName = createCompositeName(namespace, name);
-        return Settings.Config.getString(contentResolver, compositeName);
+        return new Properties(namespace,
+                Settings.Config.getStrings(contentResolver, namespace, Arrays.asList(names)));
     }
 
     /**
diff --git a/core/java/android/provider/MediaStore.java b/core/java/android/provider/MediaStore.java
index 079a42d..493f9a2 100644
--- a/core/java/android/provider/MediaStore.java
+++ b/core/java/android/provider/MediaStore.java
@@ -47,6 +47,7 @@
 import android.graphics.PostProcessor;
 import android.media.ExifInterface;
 import android.media.MediaFile;
+import android.media.MediaFormat;
 import android.net.Uri;
 import android.os.Bundle;
 import android.os.CancellationSignal;
@@ -3007,22 +3008,32 @@
             public static final String BOOKMARK = "bookmark";
 
             /**
-             * The standard of color aspects
-             * @hide
+             * The color standard of this media file, if available.
+             *
+             * @see MediaFormat#COLOR_STANDARD_BT709
+             * @see MediaFormat#COLOR_STANDARD_BT601_PAL
+             * @see MediaFormat#COLOR_STANDARD_BT601_NTSC
+             * @see MediaFormat#COLOR_STANDARD_BT2020
              */
             @Column(value = Cursor.FIELD_TYPE_INTEGER, readOnly = true)
             public static final String COLOR_STANDARD = "color_standard";
 
             /**
-             * The transfer of color aspects
-             * @hide
+             * The color transfer of this media file, if available.
+             *
+             * @see MediaFormat#COLOR_TRANSFER_LINEAR
+             * @see MediaFormat#COLOR_TRANSFER_SDR_VIDEO
+             * @see MediaFormat#COLOR_TRANSFER_ST2084
+             * @see MediaFormat#COLOR_TRANSFER_HLG
              */
             @Column(value = Cursor.FIELD_TYPE_INTEGER, readOnly = true)
             public static final String COLOR_TRANSFER = "color_transfer";
 
             /**
-             * The range of color aspects
-             * @hide
+             * The color range of this media file, if available.
+             *
+             * @see MediaFormat#COLOR_RANGE_LIMITED
+             * @see MediaFormat#COLOR_RANGE_FULL
              */
             @Column(value = Cursor.FIELD_TYPE_INTEGER, readOnly = true)
             public static final String COLOR_RANGE = "color_range";
diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java
index 3c26df3..457dcc0 100644
--- a/core/java/android/provider/Settings.java
+++ b/core/java/android/provider/Settings.java
@@ -84,8 +84,10 @@
 import java.lang.annotation.Retention;
 import java.lang.annotation.RetentionPolicy;
 import java.net.URISyntaxException;
+import java.util.ArrayList;
 import java.util.HashMap;
 import java.util.HashSet;
+import java.util.List;
 import java.util.Locale;
 import java.util.Map;
 import java.util.Set;
@@ -2248,7 +2250,7 @@
         private static final String NAME_EQ_PLACEHOLDER = "name=?";
 
         // Must synchronize on 'this' to access mValues and mValuesVersion.
-        private final HashMap<String, String> mValues = new HashMap<>();
+        private final ArrayMap<String, String> mValues = new ArrayMap<>();
 
         private final Uri mUri;
         @UnsupportedAppUsage
@@ -2258,15 +2260,22 @@
         // for the fast path of retrieving settings.
         private final String mCallGetCommand;
         private final String mCallSetCommand;
+        private final String mCallListCommand;
 
         @GuardedBy("this")
         private GenerationTracker mGenerationTracker;
 
         public NameValueCache(Uri uri, String getCommand, String setCommand,
                 ContentProviderHolder providerHolder) {
+            this(uri, getCommand, setCommand, null, providerHolder);
+        }
+
+        NameValueCache(Uri uri, String getCommand, String setCommand, String listCommand,
+                ContentProviderHolder providerHolder) {
             mUri = uri;
             mCallGetCommand = getCommand;
             mCallSetCommand = setCommand;
+            mCallListCommand = listCommand;
             mProviderHolder = providerHolder;
         }
 
@@ -2448,8 +2457,8 @@
 
                 String value = c.moveToNext() ? c.getString(0) : null;
                 synchronized (NameValueCache.this) {
-                    if(mGenerationTracker != null &&
-                            currentGeneration == mGenerationTracker.getCurrentGeneration()) {
+                    if (mGenerationTracker != null
+                            && currentGeneration == mGenerationTracker.getCurrentGeneration()) {
                         mValues.put(name, value);
                     }
                 }
@@ -2466,6 +2475,141 @@
             }
         }
 
+        public ArrayMap<String, String> getStringsForPrefix(ContentResolver cr, String prefix,
+                List<String> names) {
+            ArrayMap<String, String> keyValues = new ArrayMap<>();
+            int currentGeneration = -1;
+
+            synchronized (NameValueCache.this) {
+                if (mGenerationTracker != null) {
+                    if (mGenerationTracker.isGenerationChanged()) {
+                        if (DEBUG) {
+                            Log.i(TAG, "Generation changed for type:" + mUri.getPath()
+                                    + " in package:" + cr.getPackageName());
+                        }
+                        mValues.clear();
+                    } else {
+                        boolean prefixCached = false;
+                        int size = mValues.size();
+                        for (int i = 0; i < size; ++i) {
+                            if (mValues.keyAt(i).startsWith(prefix + "/")) {
+                                prefixCached = true;
+                                break;
+                            }
+                        }
+                        if (prefixCached) {
+                            if (!names.isEmpty()) {
+                                for (String name : names) {
+                                    if (mValues.containsKey(name)) {
+                                        keyValues.put(name, mValues.get(name));
+                                    }
+                                }
+                            } else {
+                                for (int i = 0; i < size; ++i) {
+                                    String key = mValues.keyAt(i);
+                                    if (key.startsWith(prefix + "/")) {
+                                        keyValues.put(key, mValues.get(key));
+                                    }
+                                }
+                            }
+                            return keyValues;
+                        }
+                    }
+                    if (mGenerationTracker != null) {
+                        currentGeneration = mGenerationTracker.getCurrentGeneration();
+                    }
+                }
+            }
+
+            if (mCallListCommand == null) {
+                // No list command specified, return empty map
+                return keyValues;
+            }
+            IContentProvider cp = mProviderHolder.getProvider(cr);
+
+            try {
+                Bundle args = new Bundle();
+                args.putString(Settings.CALL_METHOD_PREFIX_KEY, prefix);
+                boolean needsGenerationTracker = false;
+                synchronized (NameValueCache.this) {
+                    if (mGenerationTracker == null) {
+                        needsGenerationTracker = true;
+                        args.putString(CALL_METHOD_TRACK_GENERATION_KEY, null);
+                        if (DEBUG) {
+                            Log.i(TAG, "Requested generation tracker for type: "
+                                    + mUri.getPath() + " in package:" + cr.getPackageName());
+                        }
+                    }
+                }
+
+                // Fetch all flags for the namespace at once for caching purposes
+                Bundle b = cp.call(cr.getPackageName(), mProviderHolder.mUri.getAuthority(),
+                        mCallListCommand, null, args);
+                if (b == null) {
+                    // Invalid response, return an empty map
+                    return keyValues;
+                }
+
+                // All flags for the namespace
+                Map<String, String> flagsToValues =
+                        (HashMap) b.getSerializable(Settings.NameValueTable.VALUE);
+                // Only the flags requested by the caller
+                if (!names.isEmpty()) {
+                    for (Map.Entry<String, String> flag : flagsToValues.entrySet()) {
+                        if (names.contains(flag.getKey())) {
+                            keyValues.put(flag.getKey(), flag.getValue());
+                        }
+                    }
+                } else {
+                    keyValues.putAll(flagsToValues);
+                }
+
+                synchronized (NameValueCache.this) {
+                    if (needsGenerationTracker) {
+                        MemoryIntArray array = b.getParcelable(
+                                CALL_METHOD_TRACK_GENERATION_KEY);
+                        final int index = b.getInt(
+                                CALL_METHOD_GENERATION_INDEX_KEY, -1);
+                        if (array != null && index >= 0) {
+                            final int generation = b.getInt(
+                                    CALL_METHOD_GENERATION_KEY, 0);
+                            if (DEBUG) {
+                                Log.i(TAG, "Received generation tracker for type:"
+                                        + mUri.getPath() + " in package:"
+                                        + cr.getPackageName() + " with index:" + index);
+                            }
+                            if (mGenerationTracker != null) {
+                                mGenerationTracker.destroy();
+                            }
+                            mGenerationTracker = new GenerationTracker(array, index,
+                                    generation, () -> {
+                                synchronized (NameValueCache.this) {
+                                    Log.e(TAG, "Error accessing generation tracker"
+                                            + " - removing");
+                                    if (mGenerationTracker != null) {
+                                        GenerationTracker generationTracker =
+                                                mGenerationTracker;
+                                        mGenerationTracker = null;
+                                        generationTracker.destroy();
+                                        mValues.clear();
+                                    }
+                                }
+                            });
+                        }
+                    }
+                    if (mGenerationTracker != null && currentGeneration
+                            == mGenerationTracker.getCurrentGeneration()) {
+                        // cache the complete list of flags for the namespace
+                        mValues.putAll(flagsToValues);
+                    }
+                }
+                return keyValues;
+            } catch (RemoteException e) {
+                // Not supported by the remote side, return an empty map
+                return keyValues;
+            }
+        }
+
         public void clearGenerationTrackerForTest() {
             synchronized (NameValueCache.this) {
                 if (mGenerationTracker != null) {
@@ -7908,16 +8052,6 @@
         public static final String NOTIFICATION_BADGING = "notification_badging";
 
         /**
-         * Whether the notification bubbles are globally enabled
-         * The value is boolean (1 or 0).
-         * @hide
-         * @deprecated use {@link Global#NOTIFICATION_BUBBLES} instead.
-         */
-        @TestApi
-        @Deprecated
-        public static final String NOTIFICATION_BUBBLES = "notification_bubbles";
-
-        /**
          * Whether notifications are dismissed by a right-to-left swipe (instead of a left-to-right
          * swipe).
          *
@@ -13509,6 +13643,7 @@
                 DeviceConfig.CONTENT_URI,
                 CALL_METHOD_GET_CONFIG,
                 CALL_METHOD_PUT_CONFIG,
+                CALL_METHOD_LIST_CONFIG,
                 sProviderHolder);
 
         /**
@@ -13525,6 +13660,37 @@
         }
 
         /**
+         * Look up a list of names in the database, based on a common prefix.
+         *
+         * @param resolver to access the database with
+         * @param prefix to apply to all of the names which will be fetched
+         * @param names to look up in the table
+         * @return a non null, but possibly empty, map from name to value for any of the names that
+         *         were found during lookup.
+         *
+         * @hide
+         */
+        @RequiresPermission(Manifest.permission.READ_DEVICE_CONFIG)
+        static Map<String, String> getStrings(@NonNull ContentResolver resolver,
+                @NonNull String prefix, @NonNull List<String> names) {
+            List<String> concatenatedNames = new ArrayList<>(names.size());
+            for (String name : names) {
+                concatenatedNames.add(prefix + "/" + name);
+            }
+
+            ArrayMap<String, String> rawKeyValues = sNameValueCache.getStringsForPrefix(
+                    resolver, prefix, concatenatedNames);
+            int size = rawKeyValues.size();
+            int substringLength = prefix.length() + 1;
+            ArrayMap<String, String> keyValues = new ArrayMap<>(size);
+            for (int i = 0; i < size; ++i) {
+                keyValues.put(rawKeyValues.keyAt(i).substring(substringLength),
+                        rawKeyValues.valueAt(i));
+            }
+            return keyValues;
+        }
+
+        /**
          * Store a name/value pair into the database.
          * <p>
          * Also the method takes an argument whether to make the value the default for this setting.
diff --git a/core/java/android/service/autofill/AutofillFieldClassificationService.java b/core/java/android/service/autofill/AutofillFieldClassificationService.java
index 320dcec6..28842a7 100644
--- a/core/java/android/service/autofill/AutofillFieldClassificationService.java
+++ b/core/java/android/service/autofill/AutofillFieldClassificationService.java
@@ -93,6 +93,13 @@
      */
     public static final String REQUIRED_ALGORITHM_EXACT_MATCH = "EXACT_MATCH";
 
+    /**
+     * Field classification algorithm that compares a credit card string to known last four digits.
+     *
+     * <p>Service implementation must provide this algorithm.</p>
+     */
+    public static final String REQUIRED_ALGORITHM_CREDIT_CARD = "CREDIT_CARD";
+
     /** {@hide} **/
     public static final String EXTRA_SCORES = "scores";
 
diff --git a/core/java/android/service/euicc/EuiccService.java b/core/java/android/service/euicc/EuiccService.java
index ff8b135..8a9f689 100644
--- a/core/java/android/service/euicc/EuiccService.java
+++ b/core/java/android/service/euicc/EuiccService.java
@@ -15,6 +15,8 @@
  */
 package android.service.euicc;
 
+import static android.telephony.euicc.EuiccCardManager.ResetOption;
+
 import android.annotation.CallSuper;
 import android.annotation.IntDef;
 import android.annotation.NonNull;
@@ -503,7 +505,7 @@
             String nickname);
 
     /**
-     * Erase all of the subscriptions on the device.
+     * Erase all operational subscriptions on the device.
      *
      * <p>This is intended to be used for device resets. As such, the reset should be performed even
      * if an active SIM must be deactivated in order to access the eUICC.
@@ -512,10 +514,31 @@
      * @return the result of the erase operation. May be one of the predefined {@code RESULT_}
      *     constants or any implementation-specific code starting with {@link #RESULT_FIRST_USER}.
      * @see android.telephony.euicc.EuiccManager#eraseSubscriptions
+     *
+     * @deprecated From R, callers should specify a flag for specific set of subscriptions to erase
+     * and use @link{onEraseSubscriptionsWithOptions} instead
      */
+    @Deprecated
     public abstract int onEraseSubscriptions(int slotId);
 
     /**
+     * Erase specific subscriptions on the device.
+     *
+     * <p>This is intended to be used for device resets. As such, the reset should be performed even
+     * if an active SIM must be deactivated in order to access the eUICC.
+     *
+     * @param slotIndex index of the SIM slot to use for the operation.
+     * @param options flag for specific group of subscriptions to erase
+     * @return the result of the erase operation. May be one of the predefined {@code RESULT_}
+     *     constants or any implementation-specific code starting with {@link #RESULT_FIRST_USER}.
+     * @see android.telephony.euicc.EuiccManager#eraseSubscriptionsWithOptions
+     */
+    public int onEraseSubscriptionsWithOptions(int slotIndex, @ResetOption int options) {
+        throw new UnsupportedOperationException(
+                "This method must be overridden to enable the ResetOption parameter");
+    }
+
+    /**
      * Ensure that subscriptions will be retained on the next factory reset.
      *
      * <p>Called directly before a factory reset. Assumes that a normal factory reset will lead to
@@ -751,6 +774,23 @@
         }
 
         @Override
+        public void eraseSubscriptionsWithOptions(
+                int slotIndex, @ResetOption int options, IEraseSubscriptionsCallback callback) {
+            mExecutor.execute(new Runnable() {
+                @Override
+                public void run() {
+                    int result = EuiccService.this.onEraseSubscriptionsWithOptions(
+                            slotIndex, options);
+                    try {
+                        callback.onComplete(result);
+                    } catch (RemoteException e) {
+                        // Can't communicate with the phone process; ignore.
+                    }
+                }
+            });
+        }
+
+        @Override
         public void retainSubscriptionsForFactoryReset(int slotId,
                 IRetainSubscriptionsForFactoryResetCallback callback) {
             mExecutor.execute(new Runnable() {
diff --git a/core/java/android/service/euicc/IEuiccService.aidl b/core/java/android/service/euicc/IEuiccService.aidl
index c2cdf09..2acc47a 100644
--- a/core/java/android/service/euicc/IEuiccService.aidl
+++ b/core/java/android/service/euicc/IEuiccService.aidl
@@ -52,6 +52,8 @@
     void updateSubscriptionNickname(int slotId, String iccid, String nickname,
             in IUpdateSubscriptionNicknameCallback callback);
     void eraseSubscriptions(int slotId, in IEraseSubscriptionsCallback callback);
+    void eraseSubscriptionsWithOptions(
+            int slotIndex, int options, in IEraseSubscriptionsCallback callback);
     void retainSubscriptionsForFactoryReset(
             int slotId, in IRetainSubscriptionsForFactoryResetCallback callback);
 }
\ No newline at end of file
diff --git a/core/java/android/speech/RecognitionService.java b/core/java/android/speech/RecognitionService.java
index 70dfef5..dfc5c82 100644
--- a/core/java/android/speech/RecognitionService.java
+++ b/core/java/android/speech/RecognitionService.java
@@ -170,13 +170,23 @@
      * Checks whether the caller has sufficient permissions
      * 
      * @param listener to send the error message to in case of error
+     * @param forDataDelivery If the permission check is for delivering the sensitive data.
      * @return {@code true} if the caller has enough permissions, {@code false} otherwise
      */
-    private boolean checkPermissions(IRecognitionListener listener) {
+    private boolean checkPermissions(IRecognitionListener listener, boolean forDataDelivery) {
         if (DBG) Log.d(TAG, "checkPermissions");
-        if (PermissionChecker.checkCallingOrSelfPermission(this,
-                android.Manifest.permission.RECORD_AUDIO) == PermissionChecker.PERMISSION_GRANTED) {
-            return true;
+        if (forDataDelivery) {
+            if (PermissionChecker.checkCallingOrSelfPermissionForDataDelivery(this,
+                    android.Manifest.permission.RECORD_AUDIO, null /*message*/)
+                             == PermissionChecker.PERMISSION_GRANTED) {
+                return true;
+            }
+        } else {
+            if (PermissionChecker.checkCallingOrSelfPermissionForPreflight(this,
+                    android.Manifest.permission.RECORD_AUDIO)
+                            == PermissionChecker.PERMISSION_GRANTED) {
+                return true;
+            }
         }
         try {
             Log.e(TAG, "call for recognition service without RECORD_AUDIO permissions");
@@ -342,7 +352,7 @@
         public void startListening(Intent recognizerIntent, IRecognitionListener listener) {
             if (DBG) Log.d(TAG, "startListening called by:" + listener.asBinder());
             final RecognitionService service = mServiceRef.get();
-            if (service != null && service.checkPermissions(listener)) {
+            if (service != null && service.checkPermissions(listener, true /*forDataDelivery*/)) {
                 service.mHandler.sendMessage(Message.obtain(service.mHandler,
                         MSG_START_LISTENING, service.new StartListeningArgs(
                                 recognizerIntent, listener, Binder.getCallingUid())));
@@ -353,7 +363,7 @@
         public void stopListening(IRecognitionListener listener) {
             if (DBG) Log.d(TAG, "stopListening called by:" + listener.asBinder());
             final RecognitionService service = mServiceRef.get();
-            if (service != null && service.checkPermissions(listener)) {
+            if (service != null && service.checkPermissions(listener, false /*forDataDelivery*/)) {
                 service.mHandler.sendMessage(Message.obtain(service.mHandler,
                         MSG_STOP_LISTENING, listener));
             }
@@ -363,7 +373,7 @@
         public void cancel(IRecognitionListener listener) {
             if (DBG) Log.d(TAG, "cancel called by:" + listener.asBinder());
             final RecognitionService service = mServiceRef.get();
-            if (service != null && service.checkPermissions(listener)) {
+            if (service != null && service.checkPermissions(listener, false /*forDataDelivery*/)) {
                 service.mHandler.sendMessage(Message.obtain(service.mHandler,
                         MSG_CANCEL, listener));
             }
diff --git a/core/java/android/text/TextUtils.java b/core/java/android/text/TextUtils.java
index 81643e9..5bda867 100644
--- a/core/java/android/text/TextUtils.java
+++ b/core/java/android/text/TextUtils.java
@@ -36,6 +36,7 @@
 import android.sysprop.DisplayProperties;
 import android.text.style.AbsoluteSizeSpan;
 import android.text.style.AccessibilityClickableSpan;
+import android.text.style.AccessibilityReplacementSpan;
 import android.text.style.AccessibilityURLSpan;
 import android.text.style.AlignmentSpan;
 import android.text.style.BackgroundColorSpan;
@@ -735,6 +736,8 @@
     /** @hide */
     public static final int LINE_HEIGHT_SPAN = 28;
     /** @hide */
+    public static final int ACCESSIBILITY_REPLACEMENT_SPAN = 29;
+    /** @hide */
     public static final int LAST_SPAN = LINE_HEIGHT_SPAN;
 
     /**
@@ -860,7 +863,7 @@
 
                 case LEADING_MARGIN_SPAN:
                     readSpan(p, sp, new LeadingMarginSpan.Standard(p));
-                break;
+                    break;
 
                 case URL_SPAN:
                     readSpan(p, sp, new URLSpan(p));
@@ -933,7 +936,11 @@
                 case LINE_HEIGHT_SPAN:
                     readSpan(p, sp, new LineHeightSpan.Standard(p));
                     break;
-                    
+
+                case ACCESSIBILITY_REPLACEMENT_SPAN:
+                    readSpan(p, sp, new AccessibilityReplacementSpan(p));
+                    break;
+
                 default:
                     throw new RuntimeException("bogus span encoding " + kind);
                 }
diff --git a/core/java/android/text/style/AccessibilityReplacementSpan.java b/core/java/android/text/style/AccessibilityReplacementSpan.java
new file mode 100644
index 0000000..07b0975
--- /dev/null
+++ b/core/java/android/text/style/AccessibilityReplacementSpan.java
@@ -0,0 +1,100 @@
+/*
+ * 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.text.style;
+
+import android.graphics.Canvas;
+import android.graphics.Paint;
+import android.os.Parcel;
+import android.os.Parcelable;
+import android.text.ParcelableSpan;
+import android.text.TextUtils;
+
+/**
+ * This class serves as a parcelable placeholder for the ReplacementSpans.
+ *
+ * This span contains content description of original span to let Accessibility service to do the
+ * substitution for it.
+ *
+ * @hide
+ */
+public class AccessibilityReplacementSpan extends ReplacementSpan
+        implements ParcelableSpan {
+    // The content description of the span this one replaces
+    private CharSequence mContentDescription;
+
+    /**
+     * @param contentDescription The content description of the span this one replaces
+     */
+    public AccessibilityReplacementSpan(CharSequence contentDescription) {
+        this.setContentDescription(contentDescription);
+        mContentDescription = contentDescription;
+    }
+
+    public AccessibilityReplacementSpan(Parcel p) {
+        mContentDescription = p.readCharSequence();
+    }
+
+    @Override
+    public int getSpanTypeId() {
+        return getSpanTypeIdInternal();
+    }
+
+    @Override
+    public int getSpanTypeIdInternal() {
+        return TextUtils.ACCESSIBILITY_REPLACEMENT_SPAN;
+    }
+
+    @Override
+    public int describeContents() {
+        return 0;
+    }
+
+    @Override
+    public void writeToParcel(Parcel dest, int flags) {
+        writeToParcelInternal(dest, flags);
+    }
+
+    @Override
+    public void writeToParcelInternal(Parcel dest, int flags) {
+        dest.writeCharSequence(mContentDescription);
+    }
+
+    @Override
+    public int getSize(Paint paint, CharSequence text, int start, int end,
+            Paint.FontMetricsInt fm) {
+        return 0;
+    }
+
+    @Override
+    public void draw(Canvas canvas, CharSequence text, int start, int end, float x, int top, int y,
+            int bottom, Paint paint) {
+    }
+
+    public static final @android.annotation.NonNull
+    Parcelable.Creator<AccessibilityReplacementSpan> CREATOR =
+            new Parcelable.Creator<AccessibilityReplacementSpan>() {
+        @Override
+        public AccessibilityReplacementSpan createFromParcel(Parcel parcel) {
+            return new AccessibilityReplacementSpan(parcel);
+        }
+
+        @Override
+        public AccessibilityReplacementSpan[] newArray(int size) {
+            return new AccessibilityReplacementSpan[size];
+        }
+    };
+}
diff --git a/core/java/android/text/style/ReplacementSpan.java b/core/java/android/text/style/ReplacementSpan.java
index 5f94ad0..0553232 100644
--- a/core/java/android/text/style/ReplacementSpan.java
+++ b/core/java/android/text/style/ReplacementSpan.java
@@ -25,6 +25,8 @@
 
 public abstract class ReplacementSpan extends MetricAffectingSpan {
 
+    private CharSequence mContentDescription = null;
+
     /**
      * Returns the width of the span. Extending classes can set the height of the span by updating
      * attributes of {@link android.graphics.Paint.FontMetricsInt}. If the span covers the whole
@@ -61,6 +63,27 @@
                               int top, int y, int bottom, @NonNull Paint paint);
 
     /**
+     * Gets a brief description of this ImageSpan for use in accessibility support.
+     *
+     * @return The content description.
+     */
+    @Nullable
+    public CharSequence getContentDescription() {
+        return mContentDescription;
+    }
+
+    /**
+     * Sets the specific content description into ImageSpan.
+     * ReplacementSpans are shared with accessibility services,
+     * but only the content description is available from them.
+     *
+     * @param contentDescription content description. The default value is null.
+     */
+    public void setContentDescription(@Nullable CharSequence contentDescription) {
+        mContentDescription = contentDescription;
+    }
+
+    /**
      * This method does nothing, since ReplacementSpans are measured
      * explicitly instead of affecting Paint properties.
      */
diff --git a/core/java/android/util/ArraySet.java b/core/java/android/util/ArraySet.java
index 44c5af2..4dda709 100644
--- a/core/java/android/util/ArraySet.java
+++ b/core/java/android/util/ArraySet.java
@@ -16,6 +16,7 @@
 
 package android.util;
 
+import android.annotation.Nullable;
 import android.annotation.TestApi;
 import android.annotation.UnsupportedAppUsage;
 
@@ -329,6 +330,18 @@
     }
 
     /**
+     * Create a new ArraySet with items from the given array
+     */
+    public ArraySet(@Nullable E[] array) {
+        this();
+        if (array != null) {
+            for (E value : array) {
+                add(value);
+            }
+        }
+    }
+
+    /**
      * Make the array map empty.  All storage is released.
      */
     @Override
diff --git a/core/java/android/util/FeatureFlagUtils.java b/core/java/android/util/FeatureFlagUtils.java
index b66764e..1be57dd 100644
--- a/core/java/android/util/FeatureFlagUtils.java
+++ b/core/java/android/util/FeatureFlagUtils.java
@@ -59,6 +59,7 @@
         DEFAULT_FLAGS.put("settings_wifi_details_datausage_header", "false");
         DEFAULT_FLAGS.put("settings_skip_direction_mutable", "true");
         DEFAULT_FLAGS.put(SETTINGS_WIFITRACKER2, "false");
+        DEFAULT_FLAGS.put("settings_work_profile", "false");
     }
 
     /**
diff --git a/core/java/android/util/OWNERS b/core/java/android/util/OWNERS
index 98297fb..8f3d9f6 100644
--- a/core/java/android/util/OWNERS
+++ b/core/java/android/util/OWNERS
@@ -1,3 +1,3 @@
 per-file FeatureFlagUtils.java = sbasi@google.com
-per-file FeatureFlagUtils.java = zhfan@google.com
+per-file FeatureFlagUtils.java = tmfang@google.com
 per-file FeatureFlagUtils.java = asapperstein@google.com
diff --git a/core/java/android/util/StatsEvent.java b/core/java/android/util/StatsEvent.java
new file mode 100644
index 0000000..91a5ec0
--- /dev/null
+++ b/core/java/android/util/StatsEvent.java
@@ -0,0 +1,331 @@
+/*
+ * 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.util;
+
+import static java.nio.charset.StandardCharsets.UTF_8;
+
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+
+import com.android.internal.annotations.GuardedBy;
+
+/**
+ * StatsEvent builds and stores the buffer sent over the statsd socket.
+ * This class defines and encapsulates the socket protocol.
+ * @hide
+ **/
+public final class StatsEvent implements AutoCloseable {
+    private static final int POS_NUM_ELEMENTS = 1;
+    private static final int POS_TIMESTAMP = POS_NUM_ELEMENTS + 1;
+
+    private static final int LOGGER_ENTRY_MAX_PAYLOAD = 4068;
+
+    // Max payload size is 4 KB less 4 bytes which are reserved for statsEventTag.
+    // See android_util_StatsLog.cpp.
+    private static final int MAX_EVENT_PAYLOAD = LOGGER_ENTRY_MAX_PAYLOAD - 4;
+
+    private static final byte INT_TYPE = 0;
+    private static final byte LONG_TYPE = 1;
+    private static final byte STRING_TYPE = 2;
+    private static final byte LIST_TYPE = 3;
+    private static final byte FLOAT_TYPE = 4;
+
+    private static final int INT_TYPE_SIZE = 5;
+    private static final int FLOAT_TYPE_SIZE = 5;
+    private static final int LONG_TYPE_SIZE = 9;
+
+    private static final int STRING_TYPE_OVERHEAD = 5;
+    private static final int LIST_TYPE_OVERHEAD = 2;
+
+    public static final int SUCCESS = 0;
+    public static final int ERROR_BUFFER_LIMIT_EXCEEDED = -1;
+    public static final int ERROR_NO_TIMESTAMP = -2;
+    public static final int ERROR_TIMESTAMP_ALREADY_WRITTEN = -3;
+    public static final int ERROR_NO_ATOM_ID = -4;
+    public static final int ERROR_ATOM_ID_ALREADY_WRITTEN = -5;
+    public static final int ERROR_UID_TAG_COUNT_MISMATCH = -6;
+
+    private static Object sLock = new Object();
+
+    @GuardedBy("sLock")
+    private static StatsEvent sPool;
+
+    private final byte[] mBuffer = new byte[MAX_EVENT_PAYLOAD];
+    private int mPos;
+    private int mNumElements;
+    private int mAtomId;
+
+    private StatsEvent() {
+        // Write LIST_TYPE to buffer
+        mBuffer[0] = LIST_TYPE;
+        reset();
+    }
+
+    private void reset() {
+        // Reset state.
+        mPos = POS_TIMESTAMP;
+        mNumElements = 0;
+        mAtomId = 0;
+    }
+
+    /**
+     * Returns a StatsEvent object from the pool.
+     **/
+    @NonNull
+    public static StatsEvent obtain() {
+        final StatsEvent statsEvent;
+        synchronized (sLock) {
+            statsEvent = null == sPool ? new StatsEvent() : sPool;
+            sPool = null;
+        }
+        statsEvent.reset();
+        return statsEvent;
+    }
+
+    @Override
+    public void close() {
+        synchronized (sLock) {
+            if (null == sPool) {
+                sPool = this;
+            }
+        }
+    }
+
+    /**
+     * Writes the event timestamp to the buffer.
+     **/
+    public int writeTimestampNs(final long timestampNs) {
+        if (hasTimestamp()) {
+            return ERROR_TIMESTAMP_ALREADY_WRITTEN;
+        }
+        return writeLong(timestampNs);
+    }
+
+    private boolean hasTimestamp() {
+        return mPos > POS_TIMESTAMP;
+    }
+
+    private boolean hasAtomId() {
+        return mAtomId != 0;
+    }
+
+    /**
+     * Writes the atom id to the buffer.
+     **/
+    public int writeAtomId(final int atomId) {
+        if (!hasTimestamp()) {
+            return ERROR_NO_TIMESTAMP;
+        } else if (hasAtomId()) {
+            return ERROR_ATOM_ID_ALREADY_WRITTEN;
+        }
+
+        final int writeResult = writeInt(atomId);
+        if (SUCCESS == writeResult) {
+            mAtomId = atomId;
+        }
+        return writeResult;
+    }
+
+    /**
+     * Appends the given int to the StatsEvent buffer.
+     **/
+    public int writeInt(final int value) {
+        if (!hasTimestamp()) {
+            return ERROR_NO_TIMESTAMP;
+        } else if (!hasAtomId()) {
+            return ERROR_NO_ATOM_ID;
+        } else if (mPos + INT_TYPE_SIZE > MAX_EVENT_PAYLOAD) {
+            return ERROR_BUFFER_LIMIT_EXCEEDED;
+        }
+
+        mBuffer[mPos] = INT_TYPE;
+        copyInt(mBuffer, mPos + 1, value);
+        mPos += INT_TYPE_SIZE;
+        mNumElements++;
+        return SUCCESS;
+    }
+
+    /**
+     * Appends the given long to the StatsEvent buffer.
+     **/
+    public int writeLong(final long value) {
+        if (!hasTimestamp()) {
+            return ERROR_NO_TIMESTAMP;
+        } else if (!hasAtomId()) {
+            return ERROR_NO_ATOM_ID;
+        } else if (mPos + LONG_TYPE_SIZE > MAX_EVENT_PAYLOAD) {
+            return ERROR_BUFFER_LIMIT_EXCEEDED;
+        }
+
+        mBuffer[mPos] = LONG_TYPE;
+        copyLong(mBuffer, mPos + 1, value);
+        mPos += LONG_TYPE_SIZE;
+        mNumElements++;
+        return SUCCESS;
+    }
+
+    /**
+     * Appends the given float to the StatsEvent buffer.
+     **/
+    public int writeFloat(final float value) {
+        if (!hasTimestamp()) {
+            return ERROR_NO_TIMESTAMP;
+        } else if (!hasAtomId()) {
+            return ERROR_NO_ATOM_ID;
+        } else if (mPos + FLOAT_TYPE_SIZE > MAX_EVENT_PAYLOAD) {
+            return ERROR_BUFFER_LIMIT_EXCEEDED;
+        }
+
+        mBuffer[mPos] = FLOAT_TYPE;
+        copyInt(mBuffer, mPos + 1, Float.floatToIntBits(value));
+        mPos += FLOAT_TYPE_SIZE;
+        mNumElements++;
+        return SUCCESS;
+    }
+
+    /**
+     * Appends the given boolean to the StatsEvent buffer.
+     **/
+    public int writeBoolean(final boolean value) {
+        return writeInt(value ? 1 : 0);
+    }
+
+    /**
+     * Appends the given byte array to the StatsEvent buffer.
+     **/
+    public int writeByteArray(@NonNull final byte[] value) {
+        if (!hasTimestamp()) {
+            return ERROR_NO_TIMESTAMP;
+        } else if (!hasAtomId()) {
+            return ERROR_NO_ATOM_ID;
+        } else if (mPos + STRING_TYPE_OVERHEAD + value.length > MAX_EVENT_PAYLOAD) {
+            return ERROR_BUFFER_LIMIT_EXCEEDED;
+        }
+
+        mBuffer[mPos] = STRING_TYPE;
+        copyInt(mBuffer, mPos + 1, value.length);
+        System.arraycopy(value, 0, mBuffer, mPos + STRING_TYPE_OVERHEAD, value.length);
+        mPos += STRING_TYPE_OVERHEAD + value.length;
+        mNumElements++;
+        return SUCCESS;
+    }
+
+    /**
+     * Appends the given String to the StatsEvent buffer.
+     **/
+    public int writeString(@NonNull final String value) {
+        final byte[] valueBytes = stringToBytes(value);
+        return writeByteArray(valueBytes);
+    }
+
+    /**
+     * Appends the AttributionNode specified as array of uids and array of tags.
+     **/
+    public int writeAttributionNode(@NonNull final int[] uids, @NonNull final String[] tags) {
+        if (!hasTimestamp()) {
+            return ERROR_NO_TIMESTAMP;
+        } else if (!hasAtomId()) {
+            return ERROR_NO_ATOM_ID;
+        } else if (mPos + LIST_TYPE_OVERHEAD > MAX_EVENT_PAYLOAD) {
+            return ERROR_BUFFER_LIMIT_EXCEEDED;
+        }
+
+        final int numTags = tags.length;
+        final int numUids = uids.length;
+        if (numTags != numUids) {
+            return ERROR_UID_TAG_COUNT_MISMATCH;
+        }
+
+        int pos = mPos;
+        mBuffer[pos] = LIST_TYPE;
+        mBuffer[pos + 1] = (byte) numTags;
+        pos += LIST_TYPE_OVERHEAD;
+        for (int i = 0; i < numTags; i++) {
+            final byte[] tagBytes = stringToBytes(tags[i]);
+
+            if (pos + LIST_TYPE_OVERHEAD + INT_TYPE_SIZE
+                    + STRING_TYPE_OVERHEAD + tagBytes.length > MAX_EVENT_PAYLOAD) {
+                return ERROR_BUFFER_LIMIT_EXCEEDED;
+            }
+
+            mBuffer[pos] = LIST_TYPE;
+            mBuffer[pos + 1] = 2;
+            pos += LIST_TYPE_OVERHEAD;
+            mBuffer[pos] = INT_TYPE;
+            copyInt(mBuffer, pos + 1, uids[i]);
+            pos += INT_TYPE_SIZE;
+            mBuffer[pos] = STRING_TYPE;
+            copyInt(mBuffer, pos + 1, tagBytes.length);
+            System.arraycopy(tagBytes, 0, mBuffer, pos + STRING_TYPE_OVERHEAD, tagBytes.length);
+            pos += STRING_TYPE_OVERHEAD + tagBytes.length;
+        }
+        mPos = pos;
+        mNumElements++;
+        return SUCCESS;
+    }
+
+    /**
+     * Returns the byte array containing data in the statsd socket format.
+     * @hide
+     **/
+    @NonNull
+    public byte[] getBuffer() {
+        // Encode number of elements in the buffer.
+        mBuffer[POS_NUM_ELEMENTS] = (byte) mNumElements;
+        return mBuffer;
+    }
+
+    /**
+     * Returns number of bytes used by the buffer.
+     * @hide
+     **/
+    public int size() {
+        return mPos;
+    }
+
+    /**
+     * Getter for atom id.
+     * @hide
+     **/
+    public int getAtomId() {
+        return mAtomId;
+    }
+
+    @NonNull
+    private static byte[] stringToBytes(@Nullable final String value) {
+        return (null == value ? "" : value).getBytes(UTF_8);
+    }
+
+    // Helper methods for copying primitives
+    private static void copyInt(@NonNull byte[] buff, int pos, int value) {
+        buff[pos] = (byte) (value);
+        buff[pos + 1] = (byte) (value >> 8);
+        buff[pos + 2] = (byte) (value >> 16);
+        buff[pos + 3] = (byte) (value >> 24);
+    }
+
+    private static void copyLong(@NonNull byte[] buff, int pos, long value) {
+        buff[pos] = (byte) (value);
+        buff[pos + 1] = (byte) (value >> 8);
+        buff[pos + 2] = (byte) (value >> 16);
+        buff[pos + 3] = (byte) (value >> 24);
+        buff[pos + 4] = (byte) (value >> 32);
+        buff[pos + 5] = (byte) (value >> 40);
+        buff[pos + 6] = (byte) (value >> 48);
+        buff[pos + 7] = (byte) (value >> 56);
+    }
+}
diff --git a/core/java/android/view/IWindow.aidl b/core/java/android/view/IWindow.aidl
index f34f9e6..4b872d3 100644
--- a/core/java/android/view/IWindow.aidl
+++ b/core/java/android/view/IWindow.aidl
@@ -73,6 +73,14 @@
      */
     void insetsControlChanged(in InsetsState insetsState, in InsetsSourceControl[] activeControls);
 
+    /**
+     * Called when a set of insets source window should be shown by policy.
+     *
+     * @param types internal inset types (WindowInsets.Type.InsetType) to show
+     * @param fromIme true if this request originated from IME (InputMethodService).
+     */
+    void showInsets(int types, boolean fromIme);
+
     void moved(int newX, int newY);
     void dispatchAppVisibility(boolean visible);
     void dispatchGetNewSurface();
diff --git a/core/java/android/view/IWindowManager.aidl b/core/java/android/view/IWindowManager.aidl
index 49e8800..35cfe9e 100644
--- a/core/java/android/view/IWindowManager.aidl
+++ b/core/java/android/view/IWindowManager.aidl
@@ -644,4 +644,16 @@
      * Enables/disables SurfaceFlinger layer tracing.
      */
     void setLayerTracing(boolean enabled);
+
+    /**
+     * Mirrors a specified display. The root of the mirrored hierarchy will be stored in
+     * outSurfaceControl.
+     * Requires the ACCESS_SURFACE_FLINGER permission.
+     *
+     * @param displayId The id of the display to mirror
+     * @param outSurfaceControl The SurfaceControl for the root of the mirrored hierarchy.
+     *
+     * @return true if the display was successfully mirrored.
+     */
+    boolean mirrorDisplay(int displayId, out SurfaceControl outSurfaceControl);
 }
diff --git a/core/java/android/view/InputWindowHandle.java b/core/java/android/view/InputWindowHandle.java
index 10a9aaa..08e4eeb 100644
--- a/core/java/android/view/InputWindowHandle.java
+++ b/core/java/android/view/InputWindowHandle.java
@@ -38,10 +38,8 @@
     // The input application handle.
     public final InputApplicationHandle inputApplicationHandle;
 
-    // The client window.
-    public final IWindow clientWindow;
-
-    // The token associated with the window.
+    // The token associates input data with a window and its input channel. The client input
+    // channel and the server input channel will both contain this token.
     public IBinder token;
 
     // The window name.
@@ -120,10 +118,8 @@
 
     private native void nativeDispose();
 
-    public InputWindowHandle(InputApplicationHandle inputApplicationHandle,
-            IWindow clientWindow, int displayId) {
+    public InputWindowHandle(InputApplicationHandle inputApplicationHandle, int displayId) {
         this.inputApplicationHandle = inputApplicationHandle;
-        this.clientWindow = clientWindow;
         this.displayId = displayId;
     }
 
diff --git a/core/java/android/view/InsetsController.java b/core/java/android/view/InsetsController.java
index c798d85..5a8636d 100644
--- a/core/java/android/view/InsetsController.java
+++ b/core/java/android/view/InsetsController.java
@@ -224,7 +224,7 @@
         show(types, false /* fromIme */);
     }
 
-    private void show(@InsetType int types, boolean fromIme) {
+    void show(@InsetType int types, boolean fromIme) {
         // TODO: Support a ResultReceiver for IME.
         // TODO(b/123718661): Make show() work for multi-session IME.
         int typesReady = 0;
diff --git a/core/java/android/view/SurfaceControl.java b/core/java/android/view/SurfaceControl.java
index 6639fbf..8dd475e 100644
--- a/core/java/android/view/SurfaceControl.java
+++ b/core/java/android/view/SurfaceControl.java
@@ -91,7 +91,7 @@
             boolean captureSecureLayers);
     private static native ScreenshotGraphicBuffer nativeCaptureLayers(IBinder displayToken,
             long layerObject, Rect sourceCrop, float frameScale, long[] excludeLayerObjects);
-
+    private static native long nativeMirrorSurface(long mirrorOfObject);
     private static native long nativeCreateTransaction();
     private static native long nativeGetNativeTransactionFinalizer();
     private static native void nativeApplyTransaction(long transactionObj, boolean sync);
@@ -181,7 +181,6 @@
     private static native void nativeSeverChildren(long transactionObj, long nativeObject);
     private static native void nativeSetOverrideScalingMode(long transactionObj, long nativeObject,
             int scalingMode);
-    private static native boolean nativeGetTransformToDisplayInverse(long nativeObject);
 
     private static native Display.HdrCapabilities nativeGetHdrCapabilities(IBinder displayToken);
 
@@ -200,7 +199,10 @@
 
     private final CloseGuard mCloseGuard = CloseGuard.get();
     private String mName;
-    long mNativeObject; // package visibility only for Surface.java access
+    /**
+     * @hide
+     */
+    public long mNativeObject;
 
     // TODO: Move this to native.
     private final Object mSizeLock = new Object();
@@ -303,8 +305,8 @@
     /**
      * Surface creation flag: Creates a Dim surface.
      * Everything behind this surface is dimmed by the amount specified
-     * in {@link #setAlpha}.  It is an error to lock a Dim surface, since it
-     * doesn't have a backing store.
+     * in {@link Transaction#setAlpha(SurfaceControl, float)}.  It is an error to lock a Dim
+     * surface, since it doesn't have a backing store.
      *
      * @hide
      */
@@ -319,6 +321,11 @@
     public static final int FX_SURFACE_CONTAINER = 0x00080000;
 
     /**
+     * @hide
+     */
+    public static final int FX_SURFACE_BLAST = 0x00040000;
+
+    /**
      * Mask used for FX values above.
      *
      * @hide
@@ -694,6 +701,14 @@
         }
 
         /**
+         * @hide
+         */
+        public Builder setBLASTLayer() {
+            unsetBufferSize();
+            return setFlags(FX_SURFACE_BLAST, FX_SURFACE_MASK);
+        }
+
+        /**
          * Indicates whether a 'ContainerLayer' is to be constructed.
          *
          * Container layers will not be rendered in any fashion and instead are used
@@ -740,20 +755,20 @@
      * <p>
      * Good practice is to first create the surface with the {@link #HIDDEN} flag
      * specified, open a transaction, set the surface layer, layer stack, alpha,
-     * and position, call {@link #show} if appropriate, and close the transaction.
+     * and position, call {@link Transaction#show(SurfaceControl)} if appropriate, and close the
+     * transaction.
      * <p>
      * Bounds of the surface is determined by its crop and its buffer size. If the
      * surface has no buffer or crop, the surface is boundless and only constrained
      * by the size of its parent bounds.
      *
-     * @param session The surface session, must not be null.
-     * @param name The surface name, must not be null.
-     * @param w The surface initial width.
-     * @param h The surface initial height.
-     * @param flags The surface creation flags.  Should always include {@link #HIDDEN}
-     * in the creation flags.
+     * @param session  The surface session, must not be null.
+     * @param name     The surface name, must not be null.
+     * @param w        The surface initial width.
+     * @param h        The surface initial height.
+     * @param flags    The surface creation flags.  Should always include {@link #HIDDEN}
+     *                 in the creation flags.
      * @param metadata Initial metadata.
-     *
      * @throws throws OutOfResourcesException If the SurfaceControl cannot be created.
      */
     private SurfaceControl(SurfaceSession session, String name, int w, int h, int format, int flags,
@@ -1014,15 +1029,6 @@
     /**
      * @hide
      */
-    public void deferTransactionUntil(Surface barrier, long frame) {
-        synchronized(SurfaceControl.class) {
-            sGlobalTransaction.deferTransactionUntilSurface(this, barrier, frame);
-        }
-    }
-
-    /**
-     * @hide
-     */
     public void reparentChildren(SurfaceControl newParent) {
         synchronized(SurfaceControl.class) {
             sGlobalTransaction.reparentChildren(this, newParent);
@@ -1032,15 +1038,6 @@
     /**
      * @hide
      */
-    public void reparent(SurfaceControl newParent) {
-        synchronized(SurfaceControl.class) {
-            sGlobalTransaction.reparent(this, newParent);
-        }
-    }
-
-    /**
-     * @hide
-     */
     public void detachChildren() {
         synchronized(SurfaceControl.class) {
             sGlobalTransaction.detachChildren(this);
@@ -1060,15 +1057,6 @@
     /**
      * @hide
      */
-    public static void setAnimationTransaction() {
-        synchronized (SurfaceControl.class) {
-            sGlobalTransaction.setAnimationTransaction();
-        }
-    }
-
-    /**
-     * @hide
-     */
     @UnsupportedAppUsage
     public void setLayer(int zorder) {
         checkNotReleased();
@@ -1080,16 +1068,6 @@
     /**
      * @hide
      */
-    public void setRelativeLayer(SurfaceControl relativeTo, int zorder) {
-        checkNotReleased();
-        synchronized(SurfaceControl.class) {
-            sGlobalTransaction.setRelativeLayer(this, relativeTo, zorder);
-        }
-    }
-
-    /**
-     * @hide
-     */
     @UnsupportedAppUsage
     public void setPosition(float x, float y) {
         checkNotReleased();
@@ -1183,16 +1161,6 @@
     /**
      * @hide
      */
-    public void setColor(@Size(3) float[] color) {
-        checkNotReleased();
-        synchronized (SurfaceControl.class) {
-            sGlobalTransaction.setColor(this, color);
-        }
-    }
-
-    /**
-     * @hide
-     */
     public void setMatrix(float dsdx, float dtdx, float dtdy, float dsdy) {
         checkNotReleased();
         synchronized(SurfaceControl.class) {
@@ -1201,36 +1169,6 @@
     }
 
     /**
-     * Sets the transform and position of a {@link SurfaceControl} from a 3x3 transformation matrix.
-     *
-     * @param matrix The matrix to apply.
-     * @param float9 An array of 9 floats to be used to extract the values from the matrix.
-     * @hide
-     */
-    public void setMatrix(Matrix matrix, float[] float9) {
-        checkNotReleased();
-        matrix.getValues(float9);
-        synchronized (SurfaceControl.class) {
-            sGlobalTransaction.setMatrix(this, float9[MSCALE_X], float9[MSKEW_Y],
-                    float9[MSKEW_X], float9[MSCALE_Y]);
-            sGlobalTransaction.setPosition(this, float9[MTRANS_X], float9[MTRANS_Y]);
-        }
-    }
-
-    /**
-     * Sets the color transform for the Surface.
-     * @param matrix A float array with 9 values represents a 3x3 transform matrix
-     * @param translation A float array with 3 values represents a translation vector
-     * @hide
-     */
-    public void setColorTransform(@Size(9) float[] matrix, @Size(3) float[] translation) {
-        checkNotReleased();
-        synchronized (SurfaceControl.class) {
-            sGlobalTransaction.setColorTransform(this, matrix, translation);
-        }
-    }
-
-    /**
      * Sets the Surface to be color space agnostic. If a surface is color space agnostic,
      * the color can be interpreted in any color space.
      * @param agnostic A boolean to indicate whether the surface is color space agnostic
@@ -1260,43 +1198,6 @@
     }
 
     /**
-     * Same as {@link SurfaceControl#setWindowCrop(Rect)} but sets the crop rect top left at 0, 0.
-     *
-     * @param width width of crop rect
-     * @param height height of crop rect
-     * @hide
-     */
-    public void setWindowCrop(int width, int height) {
-        checkNotReleased();
-        synchronized (SurfaceControl.class) {
-            sGlobalTransaction.setWindowCrop(this, width, height);
-        }
-    }
-
-    /**
-     * Sets the corner radius of a {@link SurfaceControl}.
-     *
-     * @param cornerRadius Corner radius in pixels.
-     * @hide
-     */
-    public void setCornerRadius(float cornerRadius) {
-        checkNotReleased();
-        synchronized (SurfaceControl.class) {
-            sGlobalTransaction.setCornerRadius(this, cornerRadius);
-        }
-    }
-
-    /**
-     * @hide
-     */
-    public void setLayerStack(int layerStack) {
-        checkNotReleased();
-        synchronized(SurfaceControl.class) {
-            sGlobalTransaction.setLayerStack(this, layerStack);
-        }
-    }
-
-    /**
      * @hide
      */
     public void setOpaque(boolean isOpaque) {
@@ -2034,6 +1935,28 @@
         return nativeSetDisplayBrightness(displayToken, brightness);
     }
 
+    /**
+     * Creates a mirrored hierarchy for the mirrorOf {@link SurfaceControl}
+     *
+     * Real Hierarchy    Mirror
+     *                     SC (value that's returned)
+     *                      |
+     *      A               A'
+     *      |               |
+     *      B               B'
+     *
+     * @param mirrorOf The root of the hierarchy that should be mirrored.
+     * @return A SurfaceControl that's the parent of the root of the mirrored hierarchy.
+     *
+     * @hide
+     */
+    public static SurfaceControl mirrorSurface(SurfaceControl mirrorOf) {
+        long nativeObj = nativeMirrorSurface(mirrorOf.mNativeObject);
+        SurfaceControl sc = new SurfaceControl();
+        sc.assignNativeObject(nativeObj);
+        return sc;
+    }
+
      /**
      * An atomic set of changes to a set of SurfaceControl.
      */
@@ -2044,7 +1967,10 @@
         public static final NativeAllocationRegistry sRegistry = new NativeAllocationRegistry(
                 Transaction.class.getClassLoader(),
                 nativeGetNativeTransactionFinalizer(), 512);
-        private long mNativeObject;
+        /**
+         * @hide
+         */
+        public long mNativeObject;
 
         private final ArrayMap<SurfaceControl, Point> mResizedSurfaces = new ArrayMap<>();
         Runnable mFreeNativeResources;
@@ -2280,6 +2206,12 @@
         }
 
         /**
+         * Sets the transform and position of a {@link SurfaceControl} from a 3x3 transformation
+         * matrix.
+         *
+         * @param sc     SurfaceControl to set matrix of
+         * @param matrix The matrix to apply.
+         * @param float9 An array of 9 floats to be used to extract the values from the matrix.
          * @hide
          */
         @UnsupportedAppUsage
@@ -2293,7 +2225,9 @@
 
         /**
          * Sets the color transform for the Surface.
-         * @param matrix A float array with 9 values represents a 3x3 transform matrix
+         *
+         * @param sc          SurfaceControl to set color transform of
+         * @param matrix      A float array with 9 values represents a 3x3 transform matrix
          * @param translation A float array with 3 values represents a translation vector
          * @hide
          */
@@ -2317,6 +2251,13 @@
         }
 
         /**
+         * Bounds the surface and its children to the bounds specified. Size of the surface will be
+         * ignored and only the crop and buffer size will be used to determine the bounds of the
+         * surface. If no crop is specified and the surface has no buffer, the surface bounds is
+         * only constrained by the size of its parent bounds.
+         *
+         * @param sc   SurfaceControl to set crop of.
+         * @param crop Bounds of the crop to apply.
          * @hide
          */
         @UnsupportedAppUsage
@@ -2333,6 +2274,12 @@
         }
 
         /**
+         * Same as {@link Transaction#setWindowCrop(SurfaceControl, Rect)} but sets the crop rect
+         * top left at 0, 0.
+         *
+         * @param sc     SurfaceControl to set crop of.
+         * @param width  width of crop rect
+         * @param height height of crop rect
          * @hide
          */
         public Transaction setWindowCrop(SurfaceControl sc, int width, int height) {
diff --git a/core/java/android/view/SurfaceView.java b/core/java/android/view/SurfaceView.java
index a858300..2f0a4eb 100644
--- a/core/java/android/view/SurfaceView.java
+++ b/core/java/android/view/SurfaceView.java
@@ -418,12 +418,7 @@
                     Log.d(TAG, System.identityHashCode(this)
                             + " updateSurfaceAlpha: set alpha=" + alpha);
                 }
-                SurfaceControl.openTransaction();
-                try {
-                    mSurfaceControl.setAlpha(alpha);
-                } finally {
-                    SurfaceControl.closeTransaction();
-                }
+                mTmpTransaction.setAlpha(mSurfaceControl, alpha).apply();
             }
             mSurfaceAlpha = alpha;
         }
@@ -701,17 +696,18 @@
         }
     }
 
-    private void updateBackgroundVisibilityInTransaction() {
+    private void updateBackgroundVisibility(Transaction t) {
         if (mBackgroundControl == null) {
             return;
         }
         if ((mSubLayer < 0) && ((mSurfaceFlags & SurfaceControl.OPAQUE) != 0)) {
-            mBackgroundControl.show();
+            t.show(mBackgroundControl);
         } else {
-            mBackgroundControl.hide();
+            t.hide(mBackgroundControl);
         }
     }
 
+
     private void releaseSurfaces() {
         mSurfaceAlpha = 1f;
 
@@ -853,60 +849,60 @@
                     if (DEBUG) Log.i(TAG, System.identityHashCode(this) + " "
                             + "Cur surface: " + mSurface);
 
-                    SurfaceControl.openTransaction();
-                    try {
-                        // If we are creating the surface control or the parent surface has not
-                        // changed, then set relative z. Otherwise allow the parent
-                        // SurfaceChangedCallback to update the relative z. This is needed so that
-                        // we do not change the relative z before the server is ready to swap the
-                        // parent surface.
-                        if (creating || (mParentSurfaceGenerationId
-                                == viewRoot.mSurface.getGenerationId())) {
-                            SurfaceControl.mergeToGlobalTransaction(updateRelativeZ());
-                        }
-                        mParentSurfaceGenerationId = viewRoot.mSurface.getGenerationId();
-
-                        if (mViewVisibility) {
-                            mSurfaceControl.show();
-                        } else {
-                            mSurfaceControl.hide();
-                        }
-                        updateBackgroundVisibilityInTransaction();
-                        if (mUseAlpha) {
-                            mSurfaceControl.setAlpha(alpha);
-                            mSurfaceAlpha = alpha;
-                        }
-
-                        // While creating the surface, we will set it's initial
-                        // geometry. Outside of that though, we should generally
-                        // leave it to the RenderThread.
-                        //
-                        // There is one more case when the buffer size changes we aren't yet
-                        // prepared to sync (as even following the transaction applying
-                        // we still need to latch a buffer).
-                        // b/28866173
-                        if (sizeChanged || creating || !mRtHandlingPositionUpdates) {
-                            mSurfaceControl.setPosition(mScreenRect.left, mScreenRect.top);
-                            mSurfaceControl.setMatrix(mScreenRect.width() / (float) mSurfaceWidth,
-                                    0.0f, 0.0f,
-                                    mScreenRect.height() / (float) mSurfaceHeight);
-                            // Set a window crop when creating the surface or changing its size to
-                            // crop the buffer to the surface size since the buffer producer may
-                            // use SCALING_MODE_SCALE and submit a larger size than the surface
-                            // size.
-                            if (mClipSurfaceToBounds && mClipBounds != null) {
-                                mSurfaceControl.setWindowCrop(mClipBounds);
-                            } else {
-                                mSurfaceControl.setWindowCrop(mSurfaceWidth, mSurfaceHeight);
-                            }
-                        }
-                        mSurfaceControl.setCornerRadius(mCornerRadius);
-                        if (sizeChanged && !creating) {
-                            mSurfaceControl.setBufferSize(mSurfaceWidth, mSurfaceHeight);
-                        }
-                    } finally {
-                        SurfaceControl.closeTransaction();
+                    // If we are creating the surface control or the parent surface has not
+                    // changed, then set relative z. Otherwise allow the parent
+                    // SurfaceChangedCallback to update the relative z. This is needed so that
+                    // we do not change the relative z before the server is ready to swap the
+                    // parent surface.
+                    if (creating || (mParentSurfaceGenerationId
+                            == viewRoot.mSurface.getGenerationId())) {
+                        updateRelativeZ(mTmpTransaction);
                     }
+                    mParentSurfaceGenerationId = viewRoot.mSurface.getGenerationId();
+
+                    if (mViewVisibility) {
+                        mTmpTransaction.show(mSurfaceControl);
+                    } else {
+                        mTmpTransaction.hide(mSurfaceControl);
+                    }
+                    updateBackgroundVisibility(mTmpTransaction);
+                    if (mUseAlpha) {
+                        mTmpTransaction.setAlpha(mSurfaceControl, alpha);
+                        mSurfaceAlpha = alpha;
+                    }
+
+                    // While creating the surface, we will set it's initial
+                    // geometry. Outside of that though, we should generally
+                    // leave it to the RenderThread.
+                    //
+                    // There is one more case when the buffer size changes we aren't yet
+                    // prepared to sync (as even following the transaction applying
+                    // we still need to latch a buffer).
+                    // b/28866173
+                    if (sizeChanged || creating || !mRtHandlingPositionUpdates) {
+                        mTmpTransaction.setPosition(mSurfaceControl, mScreenRect.left,
+                                mScreenRect.top);
+                        mTmpTransaction.setMatrix(mSurfaceControl,
+                                mScreenRect.width() / (float) mSurfaceWidth, 0.0f, 0.0f,
+                                mScreenRect.height() / (float) mSurfaceHeight);
+                        // Set a window crop when creating the surface or changing its size to
+                        // crop the buffer to the surface size since the buffer producer may
+                        // use SCALING_MODE_SCALE and submit a larger size than the surface
+                        // size.
+                        if (mClipSurfaceToBounds && mClipBounds != null) {
+                            mTmpTransaction.setWindowCrop(mSurfaceControl, mClipBounds);
+                        } else {
+                            mTmpTransaction.setWindowCrop(mSurfaceControl, mSurfaceWidth,
+                                    mSurfaceHeight);
+                        }
+                    }
+                    mTmpTransaction.setCornerRadius(mSurfaceControl, mCornerRadius);
+                    if (sizeChanged && !creating) {
+                        mTmpTransaction.setBufferSize(mSurfaceControl, mSurfaceWidth,
+                                mSurfaceHeight);
+                    }
+
+                    mTmpTransaction.apply();
 
                     if (sizeChanged || creating) {
                         redrawNeeded = true;
@@ -1260,12 +1256,7 @@
         final float[] colorComponents = new float[] { Color.red(bgColor) / 255.f,
                 Color.green(bgColor) / 255.f, Color.blue(bgColor) / 255.f };
 
-        SurfaceControl.openTransaction();
-        try {
-            mBackgroundControl.setColor(colorComponents);
-        } finally {
-            SurfaceControl.closeTransaction();
-        }
+        mTmpTransaction.setColor(mBackgroundControl, colorComponents).apply();
     }
 
     @UnsupportedAppUsage
@@ -1480,15 +1471,13 @@
     @Override
     public void surfaceReplaced(Transaction t) {
         if (mSurfaceControl != null && mBackgroundControl != null) {
-            t.merge(updateRelativeZ());
+            updateRelativeZ(t);
         }
     }
 
-    private Transaction updateRelativeZ() {
-        Transaction t = new Transaction();
+    private void updateRelativeZ(Transaction t) {
         SurfaceControl viewRoot = getViewRootImpl().getSurfaceControl();
         t.setRelativeLayer(mBackgroundControl, viewRoot, Integer.MIN_VALUE);
         t.setRelativeLayer(mSurfaceControl, viewRoot, mSubLayer);
-        return t;
     }
 }
diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java
index cfb6a79a..1599afb 100644
--- a/core/java/android/view/View.java
+++ b/core/java/android/view/View.java
@@ -75,6 +75,7 @@
 import android.graphics.Shader;
 import android.graphics.drawable.ColorDrawable;
 import android.graphics.drawable.Drawable;
+import android.graphics.drawable.GradientDrawable;
 import android.hardware.display.DisplayManagerGlobal;
 import android.net.Uri;
 import android.os.Build;
@@ -4496,8 +4497,9 @@
      * When non-null and valid, this is expected to contain an up-to-date copy
      * of the background drawable. It is cleared on temporary detach, and reset
      * on cleanup.
+     * @hide
      */
-    private RenderNode mBackgroundRenderNode;
+    RenderNode mBackgroundRenderNode;
 
     @UnsupportedAppUsage
     private int mBackgroundResource;
@@ -5228,6 +5230,8 @@
 
             sBrokenWindowBackground = targetSdkVersion < Build.VERSION_CODES.Q;
 
+            GradientDrawable.sWrapNegativeAngleMeasurements =
+                    targetSdkVersion >= Build.VERSION_CODES.Q;
             sCompatibilityDone = true;
         }
     }
diff --git a/core/java/android/view/ViewGroup.java b/core/java/android/view/ViewGroup.java
index 82a5fa9..853a302 100644
--- a/core/java/android/view/ViewGroup.java
+++ b/core/java/android/view/ViewGroup.java
@@ -2615,7 +2615,9 @@
                     || actionMasked == MotionEvent.ACTION_CANCEL;
 
             // Update list of touch targets for pointer down, if needed.
-            final boolean split = (mGroupFlags & FLAG_SPLIT_MOTION_EVENTS) != 0;
+            final boolean isMouseEvent = ev.getSource() == InputDevice.SOURCE_MOUSE;
+            final boolean split = (mGroupFlags & FLAG_SPLIT_MOTION_EVENTS) != 0
+                    && !isMouseEvent;
             TouchTarget newTouchTarget = null;
             boolean alreadyDispatchedToNewTouchTarget = false;
             if (!canceled && !intercepted) {
@@ -2632,8 +2634,10 @@
 
                     final int childrenCount = mChildrenCount;
                     if (newTouchTarget == null && childrenCount != 0) {
-                        final float x = ev.getX(actionIndex);
-                        final float y = ev.getY(actionIndex);
+                        final float x =
+                                isMouseEvent ? ev.getXCursorPosition() : ev.getX(actionIndex);
+                        final float y =
+                                isMouseEvent ? ev.getYCursorPosition() : ev.getY(actionIndex);
                         // Find a child that can receive the event.
                         // Scan children from front to back.
                         final ArrayList<View> preorderedList = buildTouchDispatchChildList();
diff --git a/core/java/android/view/ViewRootImpl.java b/core/java/android/view/ViewRootImpl.java
index 3756a7d..9ddd84f 100644
--- a/core/java/android/view/ViewRootImpl.java
+++ b/core/java/android/view/ViewRootImpl.java
@@ -45,6 +45,7 @@
 import android.content.res.Configuration;
 import android.content.res.Resources;
 import android.content.res.TypedArray;
+import android.graphics.BLASTBufferQueue;
 import android.graphics.Canvas;
 import android.graphics.Color;
 import android.graphics.FrameInfo;
@@ -91,6 +92,7 @@
 import android.view.View.AttachInfo;
 import android.view.View.FocusDirection;
 import android.view.View.MeasureSpec;
+import android.view.WindowInsets.Type.InsetType;
 import android.view.WindowManager.LayoutParams.SoftInputModeFlags;
 import android.view.accessibility.AccessibilityEvent;
 import android.view.accessibility.AccessibilityManager;
@@ -169,6 +171,8 @@
      */
     private static final boolean MT_RENDERER_AVAILABLE = true;
 
+    private static final boolean USE_BLAST_BUFFERQUEUE = false;
+
     /**
      * If set to 2, the view system will switch from using rectangles retrieved from window to
      * dispatch to the view hierarchy to using {@link InsetsController}, that derives the insets
@@ -474,6 +478,9 @@
     @UnsupportedAppUsage
     public final Surface mSurface = new Surface();
     private final SurfaceControl mSurfaceControl = new SurfaceControl();
+    private SurfaceControl mBlastSurfaceControl;
+
+    private BLASTBufferQueue mBlastBufferQueue;
 
     /**
      * Transaction object that can be used to synchronize child SurfaceControl changes with
@@ -1281,6 +1288,11 @@
             }
             mWindowAttributes.privateFlags |= compatibleWindowFlag;
 
+            if (USE_BLAST_BUFFERQUEUE) {
+                mWindowAttributes.privateFlags =
+                    WindowManager.LayoutParams.PRIVATE_FLAG_USE_BLAST;
+            }
+
             if (mWindowAttributes.preservePreviousSurfaceInsets) {
                 // Restore old surface insets.
                 mWindowAttributes.surfaceInsets.set(
@@ -1628,6 +1640,29 @@
         return mBoundsLayer;
     }
 
+    Surface getOrCreateBLASTSurface(int width, int height) {
+        if (mSurfaceControl == null || !mSurfaceControl.isValid()) {
+            return null;
+        }
+        if (mBlastSurfaceControl == null) {
+            mBlastSurfaceControl = new SurfaceControl.Builder(mSurfaceSession)
+            .setParent(mSurfaceControl)
+            .setName("BLAST")
+            .setBLASTLayer()
+            .build();
+            mBlastBufferQueue = new BLASTBufferQueue(
+                mBlastSurfaceControl, width, height);
+
+        }
+        mBlastBufferQueue.update(mSurfaceControl, width, height);
+
+        mTransaction.show(mBlastSurfaceControl)
+            .reparent(mBlastSurfaceControl, mSurfaceControl)
+            .apply();
+
+        return mBlastBufferQueue.getSurface();
+    }
+    
     private void setBoundsLayerCrop() {
         // mWinFrame is already adjusted for surface insets. So offset it and use it as
         // the cropping bounds.
@@ -1657,6 +1692,13 @@
         }
         mSurface.release();
         mSurfaceControl.release();
+
+        if (mBlastBufferQueue != null) {
+            mTransaction.remove(mBlastSurfaceControl).apply();
+            mBlastSurfaceControl = null;
+            // We should probably add an explicit dispose.
+            mBlastBufferQueue = null;
+        }
     }
 
     /**
@@ -2412,10 +2454,9 @@
                     // will be transparent
                     if (mAttachInfo.mThreadedRenderer != null) {
                         try {
-                            hwInitialized = mAttachInfo.mThreadedRenderer.initialize(
-                                    mSurface);
+                            hwInitialized = mAttachInfo.mThreadedRenderer.initialize(mSurface);
                             if (hwInitialized && (host.mPrivateFlags
-                                    & View.PFLAG_REQUEST_TRANSPARENT_REGIONS) == 0) {
+                                            & View.PFLAG_REQUEST_TRANSPARENT_REGIONS) == 0) {
                                 // Don't pre-allocate if transparent regions
                                 // are requested as they may not be needed
                                 mAttachInfo.mThreadedRenderer.allocateBuffers();
@@ -4528,6 +4569,8 @@
     private static final int MSG_INSETS_CONTROL_CHANGED = 31;
     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;
+
 
     final class ViewRootHandler extends Handler {
         @Override
@@ -4591,6 +4634,8 @@
                     return "MSG_SYSTEM_GESTURE_EXCLUSION_CHANGED";
                 case MSG_LOCATION_IN_PARENT_DISPLAY_CHANGED:
                     return "MSG_LOCATION_IN_PARENT_DISPLAY_CHANGED";
+                case MSG_SHOW_INSETS:
+                    return "MSG_SHOW_INSETS";
             }
             return super.getMessageName(message);
         }
@@ -4705,6 +4750,10 @@
                     mInsetsController.onStateChanged((InsetsState) args.arg1);
                     break;
                 }
+                case MSG_SHOW_INSETS: {
+                    mInsetsController.show(msg.arg1, msg.arg2 == 1);
+                    break;
+                }
                 case MSG_WINDOW_MOVED:
                     if (mAdded) {
                         final int w = mWinFrame.width();
@@ -7130,7 +7179,13 @@
                 mPendingStableInsets, mPendingOutsets, mPendingBackDropFrame, mPendingDisplayCutout,
                 mPendingMergedConfiguration, mSurfaceControl, mTempInsets);
         if (mSurfaceControl.isValid()) {
-            mSurface.copyFrom(mSurfaceControl);
+            if (USE_BLAST_BUFFERQUEUE == false) {
+                mSurface.copyFrom(mSurfaceControl);
+            } else { 
+                mSurface.transferFrom(getOrCreateBLASTSurface(
+                    (int) (mView.getMeasuredWidth() * appScale + 0.5f),
+                    (int) (mView.getMeasuredHeight() * appScale + 0.5f)));
+            }
         } else {
             destroySurface();
         }
@@ -7288,26 +7343,42 @@
         }
     }
 
-    public void dumpGfxInfo(int[] info) {
-        info[0] = info[1] = 0;
-        if (mView != null) {
-            getGfxInfo(mView, info);
+    static final class GfxInfo {
+        public int viewCount;
+        public long renderNodeMemoryUsage;
+        public long renderNodeMemoryAllocated;
+
+        void add(GfxInfo other) {
+            viewCount += other.viewCount;
+            renderNodeMemoryUsage += other.renderNodeMemoryUsage;
+            renderNodeMemoryAllocated += other.renderNodeMemoryAllocated;
         }
     }
 
-    private static void getGfxInfo(View view, int[] info) {
-        RenderNode renderNode = view.mRenderNode;
-        info[0]++;
-        if (renderNode != null) {
-            info[1] += (int) renderNode.computeApproximateMemoryUsage();
+    GfxInfo getGfxInfo() {
+        GfxInfo info = new GfxInfo();
+        if (mView != null) {
+            appendGfxInfo(mView, info);
         }
+        return info;
+    }
 
+    private static void computeRenderNodeUsage(RenderNode node, GfxInfo info) {
+        if (node == null) return;
+        info.renderNodeMemoryUsage += node.computeApproximateMemoryUsage();
+        info.renderNodeMemoryAllocated += node.computeApproximateMemoryAllocated();
+    }
+
+    private static void appendGfxInfo(View view, GfxInfo info) {
+        info.viewCount++;
+        computeRenderNodeUsage(view.mRenderNode, info);
+        computeRenderNodeUsage(view.mBackgroundRenderNode, info);
         if (view instanceof ViewGroup) {
             ViewGroup group = (ViewGroup) view;
 
             int count = group.getChildCount();
             for (int i = 0; i < count; i++) {
-                getGfxInfo(group.getChildAt(i), info);
+                appendGfxInfo(group.getChildAt(i), info);
             }
         }
     }
@@ -7484,6 +7555,10 @@
         mHandler.obtainMessage(MSG_INSETS_CONTROL_CHANGED, args).sendToTarget();
     }
 
+    private void showInsets(@InsetType int types, boolean fromIme) {
+        mHandler.obtainMessage(MSG_SHOW_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) {
@@ -8599,6 +8674,14 @@
         }
 
         @Override
+        public void showInsets(@InsetType int types, boolean fromIme) {
+            final ViewRootImpl viewAncestor = mViewAncestor.get();
+            if (viewAncestor != null) {
+                viewAncestor.showInsets(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 001ab66..0b42cd9 100644
--- a/core/java/android/view/WindowManager.java
+++ b/core/java/android/view/WindowManager.java
@@ -197,12 +197,6 @@
     int TRANSIT_TASK_OPEN_BEHIND = 16;
 
     /**
-     * A window in a task is being animated in-place.
-     * @hide
-     */
-    int TRANSIT_TASK_IN_PLACE = 17;
-
-    /**
      * An activity is being relaunched (e.g. due to configuration change).
      * @hide
      */
@@ -286,7 +280,6 @@
             TRANSIT_WALLPAPER_INTRA_OPEN,
             TRANSIT_WALLPAPER_INTRA_CLOSE,
             TRANSIT_TASK_OPEN_BEHIND,
-            TRANSIT_TASK_IN_PLACE,
             TRANSIT_ACTIVITY_RELAUNCH,
             TRANSIT_DOCK_TASK_FROM_RECENTS,
             TRANSIT_KEYGUARD_GOING_AWAY,
@@ -1834,6 +1827,13 @@
         public static final int PRIVATE_FLAG_COLOR_SPACE_AGNOSTIC = 0x01000000;
 
         /**
+         * Flag to request creation of a BLAST (Buffer as LayerState) Layer.
+         * If not specified the client will receive a BufferQueue layer.
+         * @hide
+         */
+        public static final int PRIVATE_FLAG_USE_BLAST = 0x02000000;
+
+        /**
          * An internal annotation for flags that can be specified to {@link #softInputMode}.
          *
          * @hide
diff --git a/core/java/android/view/WindowManagerGlobal.java b/core/java/android/view/WindowManagerGlobal.java
index 379acbe..55b2a2a 100644
--- a/core/java/android/view/WindowManagerGlobal.java
+++ b/core/java/android/view/WindowManagerGlobal.java
@@ -604,26 +604,24 @@
 
                 pw.println("\nView hierarchy:\n");
 
-                int viewsCount = 0;
-                int displayListsSize = 0;
-                int[] info = new int[2];
+                ViewRootImpl.GfxInfo totals = new ViewRootImpl.GfxInfo();
 
                 for (int i = 0; i < count; i++) {
                     ViewRootImpl root = mRoots.get(i);
-                    root.dumpGfxInfo(info);
+                    ViewRootImpl.GfxInfo info = root.getGfxInfo();
+                    totals.add(info);
 
                     String name = getWindowName(root);
-                    pw.printf("  %s\n  %d views, %.2f kB of display lists",
-                            name, info[0], info[1] / 1024.0f);
+                    pw.printf("  %s\n  %d views, %.2f kB of render nodes",
+                            name, info.viewCount, info.renderNodeMemoryUsage / 1024.f);
                     pw.printf("\n\n");
-
-                    viewsCount += info[0];
-                    displayListsSize += info[1];
                 }
 
-                pw.printf("\nTotal ViewRootImpl: %d\n", count);
-                pw.printf("Total Views:        %d\n", viewsCount);
-                pw.printf("Total DisplayList:  %.2f kB\n\n", displayListsSize / 1024.0f);
+                pw.printf("\nTotal %-15s: %d\n", "ViewRootImpl", count);
+                pw.printf("Total %-15s: %d\n", "attached Views", totals.viewCount);
+                pw.printf("Total %-15s: %.2f kB (used) / %.2f kB (capacity)\n\n", "RenderNode",
+                        totals.renderNodeMemoryUsage / 1024.0f,
+                        totals.renderNodeMemoryAllocated / 1024.0f);
             }
         } finally {
             pw.flush();
diff --git a/core/java/android/view/accessibility/AccessibilityInteractionClient.java b/core/java/android/view/accessibility/AccessibilityInteractionClient.java
index d9fa9f2..bb10ef1 100644
--- a/core/java/android/view/accessibility/AccessibilityInteractionClient.java
+++ b/core/java/android/view/accessibility/AccessibilityInteractionClient.java
@@ -259,23 +259,38 @@
     }
 
     /**
-     * Gets the info for all windows.
+     * Gets the info for all windows of the default display.
      *
      * @param connectionId The id of a connection for interacting with the system.
      * @return The {@link AccessibilityWindowInfo} list.
      */
     public List<AccessibilityWindowInfo> getWindows(int connectionId) {
+        final SparseArray<List<AccessibilityWindowInfo>> windows =
+                getWindowsOnAllDisplays(connectionId);
+        if (windows.size() > 0) {
+            return windows.valueAt(Display.DEFAULT_DISPLAY);
+        }
+        return Collections.emptyList();
+    }
+
+    /**
+     * Gets the info for all windows of all displays.
+     *
+     * @param connectionId The id of a connection for interacting with the system.
+     * @return The SparseArray of {@link AccessibilityWindowInfo} list.
+     *         The key of SparseArray is display ID.
+     */
+    public SparseArray<List<AccessibilityWindowInfo>> getWindowsOnAllDisplays(int connectionId) {
         try {
             IAccessibilityServiceConnection connection = getConnection(connectionId);
             if (connection != null) {
-                SparseArray<List<AccessibilityWindowInfo>> allWindows =
+                SparseArray<List<AccessibilityWindowInfo>> windows =
                         sAccessibilityCache.getWindowsOnAllDisplays();
-                List<AccessibilityWindowInfo> windows;
-                if (allWindows != null) {
+                if (windows != null) {
                     if (DEBUG) {
                         Log.i(LOG_TAG, "Windows cache hit");
                     }
-                    return allWindows.valueAt(Display.DEFAULT_DISPLAY);
+                    return windows;
                 }
                 if (DEBUG) {
                     Log.i(LOG_TAG, "Windows cache miss");
@@ -287,9 +302,7 @@
                     Binder.restoreCallingIdentity(identityToken);
                 }
                 if (windows != null) {
-                    allWindows = new SparseArray<>();
-                    allWindows.put(Display.DEFAULT_DISPLAY, windows);
-                    sAccessibilityCache.setWindowsOnAllDisplays(allWindows);
+                    sAccessibilityCache.setWindowsOnAllDisplays(windows);
                     return windows;
                 }
             } else {
@@ -298,9 +311,11 @@
                 }
             }
         } catch (RemoteException re) {
-            Log.e(LOG_TAG, "Error while calling remote getWindows", re);
+            Log.e(LOG_TAG, "Error while calling remote getWindowsOnAllDisplays", re);
         }
-        return Collections.emptyList();
+
+        final SparseArray<List<AccessibilityWindowInfo>> emptyWindows = new SparseArray<>();
+        return emptyWindows;
     }
 
     /**
diff --git a/core/java/android/view/accessibility/AccessibilityManager.java b/core/java/android/view/accessibility/AccessibilityManager.java
index 2e9d881..0817452 100644
--- a/core/java/android/view/accessibility/AccessibilityManager.java
+++ b/core/java/android/view/accessibility/AccessibilityManager.java
@@ -21,6 +21,7 @@
 import android.Manifest;
 import android.accessibilityservice.AccessibilityServiceInfo;
 import android.accessibilityservice.AccessibilityServiceInfo.FeedbackType;
+import android.accessibilityservice.AccessibilityShortcutInfo;
 import android.annotation.IntDef;
 import android.annotation.NonNull;
 import android.annotation.Nullable;
@@ -30,9 +31,13 @@
 import android.annotation.SystemService;
 import android.annotation.TestApi;
 import android.annotation.UnsupportedAppUsage;
+import android.annotation.UserIdInt;
 import android.content.ComponentName;
 import android.content.Context;
+import android.content.Intent;
+import android.content.pm.ActivityInfo;
 import android.content.pm.PackageManager;
+import android.content.pm.ResolveInfo;
 import android.content.pm.ServiceInfo;
 import android.content.res.Resources;
 import android.os.Binder;
@@ -56,6 +61,9 @@
 import com.android.internal.annotations.VisibleForTesting;
 import com.android.internal.util.IntPair;
 
+import org.xmlpull.v1.XmlPullParserException;
+
+import java.io.IOException;
 import java.lang.annotation.Retention;
 import java.lang.annotation.RetentionPolicy;
 import java.util.ArrayList;
@@ -1257,6 +1265,64 @@
         return null;
     }
 
+    /**
+     * Returns the {@link AccessibilityShortcutInfo}s of the installed accessibility shortcut
+     * targets, for specific user.
+     *
+     * @param context The context of the application.
+     * @param userId The user id.
+     * @return A list with {@link AccessibilityShortcutInfo}s.
+     * @hide
+     */
+    @NonNull
+    public List<AccessibilityShortcutInfo> getInstalledAccessibilityShortcutListAsUser(
+            @NonNull Context context, @UserIdInt int userId) {
+        final List<AccessibilityShortcutInfo> shortcutInfos = new ArrayList<>();
+        final int flags = PackageManager.GET_ACTIVITIES
+                | PackageManager.GET_META_DATA
+                | PackageManager.MATCH_DISABLED_UNTIL_USED_COMPONENTS
+                | PackageManager.MATCH_DIRECT_BOOT_AWARE
+                | PackageManager.MATCH_DIRECT_BOOT_UNAWARE;
+        final Intent actionMain = new Intent(Intent.ACTION_MAIN);
+        actionMain.addCategory(Intent.CATEGORY_ACCESSIBILITY_SHORTCUT_TARGET);
+
+        final PackageManager packageManager = context.getPackageManager();
+        final List<ResolveInfo> installedShortcutList =
+                packageManager.queryIntentActivitiesAsUser(actionMain, flags, userId);
+        for (int i = 0; i < installedShortcutList.size(); i++) {
+            final AccessibilityShortcutInfo shortcutInfo =
+                    getShortcutInfo(context, installedShortcutList.get(i));
+            if (shortcutInfo != null) {
+                shortcutInfos.add(shortcutInfo);
+            }
+        }
+        return shortcutInfos;
+    }
+
+    /**
+     * Returns an {@link AccessibilityShortcutInfo} according to the given {@link ResolveInfo} of
+     * an activity.
+     *
+     * @param context The context of the application.
+     * @param resolveInfo The resolve info of an activity.
+     * @return The AccessibilityShortcutInfo.
+     */
+    @Nullable
+    private AccessibilityShortcutInfo getShortcutInfo(@NonNull Context context,
+            @NonNull ResolveInfo resolveInfo) {
+        final ActivityInfo activityInfo = resolveInfo.activityInfo;
+        if (activityInfo == null || activityInfo.metaData == null
+                || activityInfo.metaData.getInt(AccessibilityShortcutInfo.META_DATA) == 0) {
+            return null;
+        }
+        try {
+            return new AccessibilityShortcutInfo(context, activityInfo);
+        } catch (XmlPullParserException | IOException exp) {
+            Log.e(LOG_TAG, "Error while initializing AccessibilityShortcutInfo", exp);
+        }
+        return null;
+    }
+
     private IAccessibilityManager getServiceLocked() {
         if (mService == null) {
             tryConnectToServiceLocked(null);
diff --git a/core/java/android/view/accessibility/AccessibilityNodeInfo.java b/core/java/android/view/accessibility/AccessibilityNodeInfo.java
index cf29ed7..06e9d0d 100644
--- a/core/java/android/view/accessibility/AccessibilityNodeInfo.java
+++ b/core/java/android/view/accessibility/AccessibilityNodeInfo.java
@@ -39,8 +39,10 @@
 import android.text.Spanned;
 import android.text.TextUtils;
 import android.text.style.AccessibilityClickableSpan;
+import android.text.style.AccessibilityReplacementSpan;
 import android.text.style.AccessibilityURLSpan;
 import android.text.style.ClickableSpan;
+import android.text.style.ReplacementSpan;
 import android.text.style.URLSpan;
 import android.util.ArrayMap;
 import android.util.ArraySet;
@@ -2641,37 +2643,86 @@
     public void setText(CharSequence text) {
         enforceNotSealed();
         mOriginalText = text;
-        // Replace any ClickableSpans in mText with placeholders
         if (text instanceof Spanned) {
-            ClickableSpan[] spans =
-                    ((Spanned) text).getSpans(0, text.length(), ClickableSpan.class);
-            if (spans.length > 0) {
-                Spannable spannable = new SpannableStringBuilder(text);
-                for (int i = 0; i < spans.length; i++) {
-                    ClickableSpan span = spans[i];
-                    if ((span instanceof AccessibilityClickableSpan)
-                            || (span instanceof AccessibilityURLSpan)) {
-                        // We've already done enough
-                        break;
-                    }
-                    int spanToReplaceStart = spannable.getSpanStart(span);
-                    int spanToReplaceEnd = spannable.getSpanEnd(span);
-                    int spanToReplaceFlags = spannable.getSpanFlags(span);
-                    spannable.removeSpan(span);
-                    ClickableSpan replacementSpan = (span instanceof URLSpan)
-                            ? new AccessibilityURLSpan((URLSpan) span)
-                            : new AccessibilityClickableSpan(span.getId());
-                    spannable.setSpan(replacementSpan, spanToReplaceStart, spanToReplaceEnd,
-                            spanToReplaceFlags);
-                }
-                mText = spannable;
-                return;
-            }
+            CharSequence tmpText = text;
+            tmpText = replaceClickableSpan(tmpText);
+            tmpText = replaceReplacementSpan(tmpText);
+            mText = tmpText;
+            return;
         }
         mText = (text == null) ? null : text.subSequence(0, text.length());
     }
 
     /**
+     * Replaces any ClickableSpans in mText with placeholders.
+     *
+     * @param text The text.
+     *
+     * @return The spannable with ClickableSpan replacement.
+     */
+    private CharSequence replaceClickableSpan(CharSequence text) {
+        ClickableSpan[] clickableSpans =
+                ((Spanned) text).getSpans(0, text.length(), ClickableSpan.class);
+        Spannable spannable = new SpannableStringBuilder(text);
+        if (clickableSpans.length == 0) {
+            return text;
+        }
+        for (int i = 0; i < clickableSpans.length; i++) {
+            ClickableSpan span = clickableSpans[i];
+            if ((span instanceof AccessibilityClickableSpan)
+                    || (span instanceof AccessibilityURLSpan)) {
+                // We've already done enough
+                break;
+            }
+            int spanToReplaceStart = spannable.getSpanStart(span);
+            int spanToReplaceEnd = spannable.getSpanEnd(span);
+            int spanToReplaceFlags = spannable.getSpanFlags(span);
+            spannable.removeSpan(span);
+            ClickableSpan replacementSpan = (span instanceof URLSpan)
+                    ? new AccessibilityURLSpan((URLSpan) span)
+                    : new AccessibilityClickableSpan(span.getId());
+            spannable.setSpan(replacementSpan, spanToReplaceStart, spanToReplaceEnd,
+                    spanToReplaceFlags);
+        }
+        return spannable;
+    }
+
+    /**
+     * Replace any ImageSpans in mText with its content description.
+     *
+     * @param text The text.
+     *
+     * @return The spannable with ReplacementSpan replacement.
+     */
+    private CharSequence replaceReplacementSpan(CharSequence text) {
+        ReplacementSpan[] replacementSpans =
+                ((Spanned) text).getSpans(0, text.length(), ReplacementSpan.class);
+        SpannableStringBuilder spannable = new SpannableStringBuilder(text);
+        if (replacementSpans.length == 0) {
+            return text;
+        }
+        for (int i = 0; i < replacementSpans.length; i++) {
+            ReplacementSpan span = replacementSpans[i];
+            CharSequence replacementText = span.getContentDescription();
+            if (span instanceof AccessibilityReplacementSpan) {
+                // We've already done enough
+                break;
+            }
+            if (replacementText == null) {
+                continue;
+            }
+            int spanToReplaceStart = spannable.getSpanStart(span);
+            int spanToReplaceEnd = spannable.getSpanEnd(span);
+            int spanToReplaceFlags = spannable.getSpanFlags(span);
+            spannable.removeSpan(span);
+            ReplacementSpan replacementSpan = new AccessibilityReplacementSpan(replacementText);
+            spannable.setSpan(replacementSpan, spanToReplaceStart, spanToReplaceEnd,
+                    spanToReplaceFlags);
+        }
+        return spannable;
+    }
+
+    /**
      * Gets the hint text of this node. Only applies to nodes where text can be entered.
      *
      * @return The hint text.
diff --git a/core/java/android/view/accessibility/AccessibilityWindowInfo.aidl b/core/java/android/view/accessibility/AccessibilityWindowInfo.aidl
index fdb25fb..c36c4aa 100644
--- a/core/java/android/view/accessibility/AccessibilityWindowInfo.aidl
+++ b/core/java/android/view/accessibility/AccessibilityWindowInfo.aidl
@@ -17,3 +17,4 @@
 package android.view.accessibility;
 
 parcelable AccessibilityWindowInfo;
+parcelable AccessibilityWindowInfo.WindowListSparseArray;
diff --git a/core/java/android/view/accessibility/AccessibilityWindowInfo.java b/core/java/android/view/accessibility/AccessibilityWindowInfo.java
index 6a3af34..5fa8a6e 100644
--- a/core/java/android/view/accessibility/AccessibilityWindowInfo.java
+++ b/core/java/android/view/accessibility/AccessibilityWindowInfo.java
@@ -26,9 +26,12 @@
 import android.text.TextUtils;
 import android.util.LongArray;
 import android.util.Pools.SynchronizedPool;
+import android.util.SparseArray;
 import android.view.Display;
 import android.view.accessibility.AccessibilityEvent.WindowsChangeTypes;
 
+import java.util.ArrayList;
+import java.util.List;
 import java.util.Objects;
 import java.util.concurrent.atomic.AtomicInteger;
 
@@ -797,4 +800,49 @@
             return new AccessibilityWindowInfo[size];
         }
     };
+
+    /**
+     * Transfers a sparsearray with lists having {@link AccessibilityWindowInfo}s across an IPC.
+     * The key of this sparsearray is display Id.
+     *
+     * @hide
+     */
+    public static final class WindowListSparseArray
+            extends SparseArray<List<AccessibilityWindowInfo>> implements Parcelable {
+
+        @Override
+        public int describeContents() {
+            return 0;
+        }
+
+        @Override
+        public void writeToParcel(Parcel dest, int flags) {
+            final int count = size();
+            dest.writeInt(count);
+            for (int i = 0; i < count; i++) {
+                dest.writeParcelableList(valueAt(i), 0);
+                dest.writeInt(keyAt(i));
+            }
+        }
+
+        public static final Parcelable.Creator<WindowListSparseArray> CREATOR =
+                new Parcelable.Creator<WindowListSparseArray>() {
+            public WindowListSparseArray createFromParcel(
+                    Parcel source) {
+                final WindowListSparseArray array = new WindowListSparseArray();
+                final ClassLoader loader = array.getClass().getClassLoader();
+                final int count = source.readInt();
+                for (int i = 0; i < count; i++) {
+                    List<AccessibilityWindowInfo> windows = new ArrayList<>();
+                    source.readParcelableList(windows, loader);
+                    array.put(source.readInt(), windows);
+                }
+                return array;
+            }
+
+            public WindowListSparseArray[] newArray(int size) {
+                return new WindowListSparseArray[size];
+            }
+        };
+    }
 }
diff --git a/core/java/android/view/inspector/OWNERS b/core/java/android/view/inspector/OWNERS
index 4554fdc..c2827cc 100644
--- a/core/java/android/view/inspector/OWNERS
+++ b/core/java/android/view/inspector/OWNERS
@@ -1,3 +1,3 @@
 alanv@google.com
 aurimas@google.com
-emberr@google.com
+emberrose@google.com
diff --git a/core/java/android/webkit/FindAddress.java b/core/java/android/webkit/FindAddress.java
index 9183227..b146e3f6 100644
--- a/core/java/android/webkit/FindAddress.java
+++ b/core/java/android/webkit/FindAddress.java
@@ -154,7 +154,7 @@
 
     // A house number component is "one" or a number, optionally
     // followed by a single alphabetic character, or
-    private static final String HOUSE_COMPONENT = "(?:one|\\d+([a-z](?=[^a-z]|$)|st|nd|rd|th)?)";
+    private static final String HOUSE_COMPONENT = "(?:one|[0-9]+([a-z](?=[^a-z]|$)|st|nd|rd|th)?)";
 
     // House numbers are a repetition of |HOUSE_COMPONENT|, separated by -, and followed by
     // a delimiter character.
@@ -253,10 +253,10 @@
             Pattern.CASE_INSENSITIVE);
 
     private static final Pattern sSuffixedNumberRe =
-            Pattern.compile("(\\d+)(st|nd|rd|th)", Pattern.CASE_INSENSITIVE);
+            Pattern.compile("([0-9]+)(st|nd|rd|th)", Pattern.CASE_INSENSITIVE);
 
     private static final Pattern sZipCodeRe =
-            Pattern.compile("(?:\\d{5}(?:-\\d{4})?)" + WORD_END, Pattern.CASE_INSENSITIVE);
+            Pattern.compile("(?:[0-9]{5}(?:-[0-9]{4})?)" + WORD_END, Pattern.CASE_INSENSITIVE);
 
     private static boolean checkHouseNumber(String houseNumber) {
         // Make sure that there are at most 5 digits.
diff --git a/core/java/android/webkit/MimeTypeMap.java b/core/java/android/webkit/MimeTypeMap.java
index fc23c54..358fdc7 100644
--- a/core/java/android/webkit/MimeTypeMap.java
+++ b/core/java/android/webkit/MimeTypeMap.java
@@ -19,7 +19,7 @@
 import android.annotation.Nullable;
 import android.text.TextUtils;
 
-import libcore.net.MimeMap;
+import libcore.content.type.MimeMap;
 
 import java.util.regex.Pattern;
 
diff --git a/core/java/android/widget/AbsListView.java b/core/java/android/widget/AbsListView.java
index fe88a91..6d60366 100644
--- a/core/java/android/widget/AbsListView.java
+++ b/core/java/android/widget/AbsListView.java
@@ -2569,7 +2569,8 @@
 
         if (isItemClickable(view)) {
             addAccessibilityActionIfEnabled(info, isItemEnabled, AccessibilityAction.ACTION_CLICK);
-            info.setClickable(true);
+            // A disabled item is a separator which should not be clickable.
+            info.setClickable(isItemEnabled);
         }
 
         if (isLongClickable()) {
diff --git a/core/java/android/widget/TextView.java b/core/java/android/widget/TextView.java
index f997d68..31f5055 100644
--- a/core/java/android/widget/TextView.java
+++ b/core/java/android/widget/TextView.java
@@ -23,6 +23,7 @@
 import static android.view.inputmethod.CursorAnchorInfo.FLAG_HAS_VISIBLE_REGION;
 
 import android.R;
+import android.annotation.CallSuper;
 import android.annotation.CheckResult;
 import android.annotation.ColorInt;
 import android.annotation.DrawableRes;
@@ -10446,10 +10447,15 @@
     /**
      * This method is called when the selection has changed, in case any
      * subclasses would like to know.
+     * </p>
+     * <p class="note"><strong>Note:</strong> Always call the super implementation, which informs
+     * the accessibility subsystem about the selection change.
+     * </p>
      *
      * @param selStart The new selection start location.
      * @param selEnd The new selection end location.
      */
+    @CallSuper
     protected void onSelectionChanged(int selStart, int selEnd) {
         sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_TEXT_SELECTION_CHANGED);
     }
diff --git a/core/java/com/android/internal/app/ResolverListController.java b/core/java/com/android/internal/app/ResolverListController.java
index 5f92cdd..a390611 100644
--- a/core/java/com/android/internal/app/ResolverListController.java
+++ b/core/java/com/android/internal/app/ResolverListController.java
@@ -115,14 +115,6 @@
                 flags |= PackageManager.MATCH_INSTANT;
             }
             final List<ResolveInfo> infos = mpm.queryIntentActivities(intent, flags);
-            // Remove any activities that are not exported.
-            int totalSize = infos.size();
-            for (int j = totalSize - 1; j >= 0 ; j--) {
-                ResolveInfo info = infos.get(j);
-                if (info.activityInfo != null && !info.activityInfo.exported) {
-                    infos.remove(j);
-                }
-            }
             if (infos != null) {
                 if (resolvedComponents == null) {
                     resolvedComponents = new ArrayList<>();
diff --git a/core/java/com/android/internal/app/procstats/AssociationState.java b/core/java/com/android/internal/app/procstats/AssociationState.java
index 2df5158..0ed2524 100644
--- a/core/java/com/android/internal/app/procstats/AssociationState.java
+++ b/core/java/com/android/internal/app/procstats/AssociationState.java
@@ -16,7 +16,6 @@
 
 package com.android.internal.app.procstats;
 
-
 import android.annotation.Nullable;
 import android.os.Parcel;
 import android.os.SystemClock;
@@ -24,23 +23,37 @@
 import android.service.procstats.PackageAssociationProcessStatsProto;
 import android.service.procstats.PackageAssociationSourceProcessStatsProto;
 import android.util.ArrayMap;
+import android.util.Pair;
 import android.util.Slog;
 import android.util.TimeUtils;
 import android.util.proto.ProtoOutputStream;
 
 import java.io.PrintWriter;
 import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Comparator;
 import java.util.Objects;
 
 public final class AssociationState {
     private static final String TAG = "ProcessStats";
     private static final boolean DEBUG = false;
 
+    private static final boolean VALIDATE_TIMES = false;
+
     private final ProcessStats mProcessStats;
     private final ProcessStats.PackageState mPackageState;
     private final String mProcessName;
     private final String mName;
 
+    private int mTotalNesting;
+    private long mTotalStartUptime;
+    private int mTotalCount;
+    private long mTotalDuration;
+    private int mTotalActiveNesting;
+    private long mTotalActiveStartUptime;
+    private int mTotalActiveCount;
+    private long mTotalActiveDuration;
+
     public final class SourceState {
         final SourceKey mKey;
         int mProcStateSeq = -1;
@@ -55,7 +68,7 @@
         int mActiveProcState = ProcessStats.STATE_NOTHING;
         long mActiveStartUptime;
         long mActiveDuration;
-        DurationsTable mDurations;
+        DurationsTable mActiveDurations;
 
         SourceState(SourceKey key) {
             mKey = key;
@@ -97,9 +110,9 @@
         public void stop() {
             mNesting--;
             if (mNesting == 0) {
-                mDuration += SystemClock.uptimeMillis() - mStartUptime;
-                mNumActive--;
-                stopTracking(SystemClock.uptimeMillis());
+                final long now = SystemClock.uptimeMillis();
+                mDuration += now - mStartUptime;
+                stopTracking(now);
             }
         }
 
@@ -108,20 +121,25 @@
                 if (mActiveStartUptime == 0) {
                     mActiveStartUptime = now;
                     mActiveCount++;
+                    AssociationState.this.mTotalActiveNesting++;
+                    if (AssociationState.this.mTotalActiveNesting == 1) {
+                        AssociationState.this.mTotalActiveCount++;
+                        AssociationState.this.mTotalActiveStartUptime = now;
+                    }
                 }
                 if (mActiveProcState != mProcState) {
                     if (mActiveProcState != ProcessStats.STATE_NOTHING) {
                         // Currently active proc state changed, need to store the duration
                         // so far and switch tracking to the new proc state.
-                        final long duration = mActiveDuration + now - mActiveStartUptime;
-                        if (duration != 0) {
-                            if (mDurations == null) {
+                        final long addedDuration = mActiveDuration + now - mActiveStartUptime;
+                        mActiveStartUptime = now;
+                        if (addedDuration != 0) {
+                            if (mActiveDurations == null) {
                                 makeDurations();
                             }
-                            mDurations.addDuration(mActiveProcState, duration);
+                            mActiveDurations.addDuration(mActiveProcState, addedDuration);
                             mActiveDuration = 0;
                         }
-                        mActiveStartUptime = now;
                     }
                     mActiveProcState = mProcState;
                 }
@@ -135,21 +153,44 @@
                 if (!mInTrackingList) {
                     Slog.wtf(TAG, "stopActive while not tracking: " + this);
                 }
-                final long duration = mActiveDuration + now - mActiveStartUptime;
-                if (mDurations != null) {
-                    mDurations.addDuration(mActiveProcState, duration);
-                } else {
-                    mActiveDuration = duration;
-                }
+                final long addedDuration = now - mActiveStartUptime;
                 mActiveStartUptime = 0;
+                if (mActiveDurations != null) {
+                    mActiveDurations.addDuration(mActiveProcState, addedDuration);
+                } else {
+                    mActiveDuration += addedDuration;
+                }
+                AssociationState.this.mTotalActiveNesting--;
+                if (AssociationState.this.mTotalActiveNesting == 0) {
+                    AssociationState.this.mTotalActiveDuration += now
+                            - AssociationState.this.mTotalActiveStartUptime;
+                    AssociationState.this.mTotalActiveStartUptime = 0;
+                    if (VALIDATE_TIMES) {
+                        if (mActiveDuration > AssociationState.this.mTotalActiveDuration) {
+                            RuntimeException ex = new RuntimeException();
+                            ex.fillInStackTrace();
+                            Slog.w(TAG, "Source act duration " + mActiveDurations
+                                    + " exceeds total " + AssociationState.this.mTotalActiveDuration
+                                    + " in procstate " + mActiveProcState + " in source "
+                                    + mKey.mProcess + " to assoc "
+                                    + AssociationState.this.mName, ex);
+                        }
+
+                    }
+                }
             }
         }
 
         void makeDurations() {
-            mDurations = new DurationsTable(mProcessStats.mTableData);
+            mActiveDurations = new DurationsTable(mProcessStats.mTableData);
         }
 
         void stopTracking(long now) {
+            AssociationState.this.mTotalNesting--;
+            if (AssociationState.this.mTotalNesting == 0) {
+                AssociationState.this.mTotalDuration += now
+                        - AssociationState.this.mTotalStartUptime;
+            }
             stopActive(now);
             if (mInTrackingList) {
                 mInTrackingList = false;
@@ -181,7 +222,17 @@
         }
     }
 
-    private final static class SourceKey {
+    public final class SourceDumpContainer {
+        public final SourceState mState;
+        public long mTotalTime;
+        public long mActiveTime;
+
+        public SourceDumpContainer(SourceState state) {
+            mState = state;
+        }
+    }
+
+    public static final class SourceKey {
         /**
          * UID, consider this final.  Not final just to avoid a temporary object during lookup.
          */
@@ -239,12 +290,10 @@
      */
     private final ArrayMap<SourceKey, SourceState> mSources = new ArrayMap<>();
 
-    private final SourceKey mTmpSourceKey = new SourceKey(0, null, null);
+    private static final SourceKey sTmpSourceKey = new SourceKey(0, null, null);
 
     private ProcessState mProc;
 
-    private int mNumActive;
-
     public AssociationState(ProcessStats processStats, ProcessStats.PackageState packageState,
             String name, String processName, ProcessState proc) {
         mProcessStats = processStats;
@@ -278,11 +327,24 @@
         mProc = proc;
     }
 
+    public long getTotalDuration(long now) {
+        return mTotalDuration
+                + (mTotalNesting > 0 ? (now - mTotalStartUptime) : 0);
+    }
+
+    public long getActiveDuration(long now) {
+        return mTotalActiveDuration
+                + (mTotalActiveNesting > 0 ? (now - mTotalActiveStartUptime) : 0);
+    }
+
     public SourceState startSource(int uid, String processName, String packageName) {
-        mTmpSourceKey.mUid = uid;
-        mTmpSourceKey.mProcess = processName;
-        mTmpSourceKey.mPackage = packageName;
-        SourceState src = mSources.get(mTmpSourceKey);
+        SourceState src;
+        synchronized (sTmpSourceKey) {
+            sTmpSourceKey.mUid = uid;
+            sTmpSourceKey.mProcess = processName;
+            sTmpSourceKey.mPackage = packageName;
+            src = mSources.get(sTmpSourceKey);
+        }
         if (src == null) {
             SourceKey key = new SourceKey(uid, processName, packageName);
             src = new SourceState(key);
@@ -290,43 +352,88 @@
         }
         src.mNesting++;
         if (src.mNesting == 1) {
+            final long now = SystemClock.uptimeMillis();
             src.mCount++;
-            src.mStartUptime = SystemClock.uptimeMillis();
-            mNumActive++;
+            src.mStartUptime = now;
+            mTotalNesting++;
+            if (mTotalNesting == 1) {
+                mTotalCount++;
+                mTotalStartUptime = now;
+            }
         }
         return src;
     }
 
     public void add(AssociationState other) {
+        mTotalCount += other.mTotalCount;
+        final long origDuration = mTotalDuration;
+        mTotalDuration += other.mTotalDuration;
+        mTotalActiveCount += other.mTotalActiveCount;
+        mTotalActiveDuration += other.mTotalActiveDuration;
         for (int isrc = other.mSources.size() - 1; isrc >= 0; isrc--) {
             final SourceKey key = other.mSources.keyAt(isrc);
             final SourceState otherSrc = other.mSources.valueAt(isrc);
             SourceState mySrc = mSources.get(key);
+            boolean newSrc = false;
             if (mySrc == null) {
                 mySrc = new SourceState(key);
                 mSources.put(key, mySrc);
+                newSrc = true;
+            }
+            if (VALIDATE_TIMES) {
+                Slog.w(TAG, "Adding tot duration " + mySrc.mDuration + "+"
+                        + otherSrc.mDuration
+                        + (newSrc ? " (new)" : " (old)") + " (total "
+                        + origDuration + "+" + other.mTotalDuration + ") in source "
+                        + mySrc.mKey.mProcess + " to assoc " + mName);
+                if ((mySrc.mDuration + otherSrc.mDuration) > mTotalDuration) {
+                    RuntimeException ex = new RuntimeException();
+                    ex.fillInStackTrace();
+                    Slog.w(TAG, "Source tot duration " + mySrc.mDuration + "+"
+                            + otherSrc.mDuration
+                            + (newSrc ? " (new)" : " (old)") + " exceeds total "
+                            + origDuration + "+" + other.mTotalDuration + " in source "
+                            + mySrc.mKey.mProcess + " to assoc " + mName, ex);
+                }
+                if (mySrc.mActiveDurations == null && otherSrc.mActiveDurations == null) {
+                    Slog.w(TAG, "Adding act duration " + mySrc.mActiveDuration
+                            + "+" + otherSrc.mActiveDuration
+                            + (newSrc ? " (new)" : " (old)") + " (total "
+                            + origDuration + "+" + other.mTotalDuration + ") in source "
+                            + mySrc.mKey.mProcess + " to assoc " + mName);
+                    if ((mySrc.mActiveDuration + otherSrc.mActiveDuration) > mTotalDuration) {
+                        RuntimeException ex = new RuntimeException();
+                        ex.fillInStackTrace();
+                        Slog.w(TAG, "Source act duration " + mySrc.mActiveDuration + "+"
+                                + otherSrc.mActiveDuration
+                                + (newSrc ? " (new)" : " (old)") + " exceeds total "
+                                + origDuration + "+" + other.mTotalDuration + " in source "
+                                + mySrc.mKey.mProcess + " to assoc " + mName, ex);
+                    }
+                }
             }
             mySrc.mCount += otherSrc.mCount;
             mySrc.mDuration += otherSrc.mDuration;
             mySrc.mActiveCount += otherSrc.mActiveCount;
-            if (otherSrc.mActiveDuration != 0 || otherSrc.mDurations != null) {
+            if (otherSrc.mActiveDuration != 0 || otherSrc.mActiveDurations != null) {
                 // Only need to do anything if the other one has some duration data.
-                if (mySrc.mDurations != null) {
+                if (mySrc.mActiveDurations != null) {
                     // If the target already has multiple durations, just add in whatever
                     // we have in the other.
-                    if (otherSrc.mDurations != null) {
-                        mySrc.mDurations.addDurations(otherSrc.mDurations);
+                    if (otherSrc.mActiveDurations != null) {
+                        mySrc.mActiveDurations.addDurations(otherSrc.mActiveDurations);
                     } else {
-                        mySrc.mDurations.addDuration(otherSrc.mActiveProcState,
+                        mySrc.mActiveDurations.addDuration(otherSrc.mActiveProcState,
                                 otherSrc.mActiveDuration);
                     }
-                } else if (otherSrc.mDurations != null) {
+                } else if (otherSrc.mActiveDurations != null) {
                     // The other one has multiple durations, but we don't.  Expand to
                     // multiple durations and copy over.
                     mySrc.makeDurations();
-                    mySrc.mDurations.addDurations(otherSrc.mDurations);
+                    mySrc.mActiveDurations.addDurations(otherSrc.mActiveDurations);
                     if (mySrc.mActiveDuration != 0) {
-                        mySrc.mDurations.addDuration(mySrc.mActiveProcState, mySrc.mActiveDuration);
+                        mySrc.mActiveDurations.addDuration(mySrc.mActiveProcState,
+                                mySrc.mActiveDuration);
                         mySrc.mActiveDuration = 0;
                         mySrc.mActiveProcState = ProcessStats.STATE_NOTHING;
                     }
@@ -334,13 +441,14 @@
                     // Both have a single inline duration...  we can either add them together,
                     // or need to expand to multiple durations.
                     if (mySrc.mActiveProcState == otherSrc.mActiveProcState) {
-                        mySrc.mDuration += otherSrc.mDuration;
+                        mySrc.mActiveDuration += otherSrc.mActiveDuration;
                     } else {
                         // The two have durations with different proc states, need to turn
                         // in to multiple durations.
                         mySrc.makeDurations();
-                        mySrc.mDurations.addDuration(mySrc.mActiveProcState, mySrc.mActiveDuration);
-                        mySrc.mDurations.addDuration(otherSrc.mActiveProcState,
+                        mySrc.mActiveDurations.addDuration(mySrc.mActiveProcState,
+                                mySrc.mActiveDuration);
+                        mySrc.mActiveDurations.addDuration(otherSrc.mActiveProcState,
                                 otherSrc.mActiveDuration);
                         mySrc.mActiveDuration = 0;
                         mySrc.mActiveProcState = ProcessStats.STATE_NOTHING;
@@ -355,12 +463,13 @@
     }
 
     public boolean isInUse() {
-        return mNumActive > 0;
+        return mTotalNesting > 0;
     }
 
     public void resetSafely(long now) {
         if (!isInUse()) {
             mSources.clear();
+            mTotalCount = mTotalActiveCount = 0;
         } else {
             // We have some active sources...  clear out everything but those.
             for (int isrc = mSources.size() - 1; isrc >= 0; isrc--) {
@@ -376,15 +485,28 @@
                         src.mActiveCount = 0;
                     }
                     src.mActiveDuration = 0;
-                    src.mDurations = null;
+                    src.mActiveDurations = null;
                 } else {
                     mSources.removeAt(isrc);
                 }
             }
+            mTotalCount = 1;
+            mTotalStartUptime = now;
+            if (mTotalActiveNesting > 0) {
+                mTotalActiveCount = 1;
+                mTotalActiveStartUptime = now;
+            } else {
+                mTotalActiveCount = 0;
+            }
         }
+        mTotalDuration = mTotalActiveDuration = 0;
     }
 
     public void writeToParcel(ProcessStats stats, Parcel out, long nowUptime) {
+        out.writeInt(mTotalCount);
+        out.writeLong(mTotalDuration);
+        out.writeInt(mTotalActiveCount);
+        out.writeLong(mTotalActiveDuration);
         final int NSRC = mSources.size();
         out.writeInt(NSRC);
         for (int isrc = 0; isrc < NSRC; isrc++) {
@@ -396,9 +518,9 @@
             out.writeInt(src.mCount);
             out.writeLong(src.mDuration);
             out.writeInt(src.mActiveCount);
-            if (src.mDurations != null) {
+            if (src.mActiveDurations != null) {
                 out.writeInt(1);
-                src.mDurations.writeToParcel(out);
+                src.mActiveDurations.writeToParcel(out);
             } else {
                 out.writeInt(0);
                 out.writeInt(src.mActiveProcState);
@@ -412,6 +534,10 @@
      * caused it to fail.
      */
     public String readFromParcel(ProcessStats stats, Parcel in, int parcelVersion) {
+        mTotalCount = in.readInt();
+        mTotalDuration = in.readLong();
+        mTotalActiveCount = in.readInt();
+        mTotalActiveDuration = in.readLong();
         final int NSRC = in.readInt();
         if (NSRC < 0 || NSRC > 100000) {
             return "Association with bad src count: " + NSRC;
@@ -427,13 +553,29 @@
             src.mActiveCount = in.readInt();
             if (in.readInt() != 0) {
                 src.makeDurations();
-                if (!src.mDurations.readFromParcel(in)) {
+                if (!src.mActiveDurations.readFromParcel(in)) {
                     return "Duration table corrupt: " + key + " <- " + src;
                 }
             } else {
                 src.mActiveProcState = in.readInt();
                 src.mActiveDuration = in.readLong();
             }
+            if (VALIDATE_TIMES) {
+                if (src.mDuration > mTotalDuration) {
+                    RuntimeException ex = new RuntimeException();
+                    ex.fillInStackTrace();
+                    Slog.w(TAG, "Reading tot duration " + src.mDuration
+                            + " exceeds total " + mTotalDuration + " in source "
+                            + src.mKey.mProcess + " to assoc " + mName, ex);
+                }
+                if (src.mActiveDurations == null && src.mActiveDuration > mTotalDuration) {
+                    RuntimeException ex = new RuntimeException();
+                    ex.fillInStackTrace();
+                    Slog.w(TAG, "Reading act duration " + src.mActiveDuration
+                            + " exceeds total " + mTotalDuration + " in source "
+                            + src.mKey.mProcess + " to assoc " + mName, ex);
+                }
+            }
             mSources.put(key, src);
         }
         return null;
@@ -448,19 +590,30 @@
                     src.mStartUptime = nowUptime;
                 }
                 if (src.mActiveStartUptime > 0) {
-                    final long duration = src.mActiveDuration + nowUptime - src.mActiveStartUptime;
-                    if (src.mDurations != null) {
-                        src.mDurations.addDuration(src.mActiveProcState, duration);
-                    } else {
-                        src.mActiveDuration = duration;
-                    }
+                    final long addedDuration = nowUptime - src.mActiveStartUptime;
                     src.mActiveStartUptime = nowUptime;
+                    if (src.mActiveDurations != null) {
+                        src.mActiveDurations.addDuration(src.mActiveProcState, addedDuration);
+                    } else {
+                        src.mActiveDuration += addedDuration;
+                    }
                 }
             }
+            if (mTotalNesting > 0) {
+                mTotalDuration += nowUptime - mTotalStartUptime;
+                mTotalStartUptime = nowUptime;
+            }
+            if (mTotalActiveNesting > 0) {
+                mTotalActiveDuration += nowUptime - mTotalActiveStartUptime;
+                mTotalActiveStartUptime = nowUptime;
+            }
         }
     }
 
     public boolean hasProcessOrPackage(String procName) {
+        if (mProcessName.equals(procName)) {
+            return true;
+        }
         final int NSRC = mSources.size();
         for (int isrc = 0; isrc < NSRC; isrc++) {
             final SourceKey key = mSources.keyAt(isrc);
@@ -471,22 +624,110 @@
         return false;
     }
 
-    public void dumpStats(PrintWriter pw, String prefix, String prefixInner, String headerPrefix,
-            long now, long totalTime, String reqPackage, boolean dumpDetails, boolean dumpAll) {
-        if (dumpAll) {
-            pw.print(prefix);
-            pw.print("mNumActive=");
-            pw.println(mNumActive);
+    static final Comparator<Pair<SourceKey, SourceDumpContainer>> ASSOCIATION_COMPARATOR =
+            (o1, o2) -> {
+        if (o1.second.mActiveTime != o2.second.mActiveTime) {
+            return o1.second.mActiveTime > o2.second.mActiveTime ? -1 : 1;
         }
-        final int NSRC = mSources.size();
-        for (int isrc = 0; isrc < NSRC; isrc++) {
-            final SourceKey key = mSources.keyAt(isrc);
-            final SourceState src = mSources.valueAt(isrc);
-            if (reqPackage != null && !reqPackage.equals(key.mProcess)
-                    && !reqPackage.equals(key.mPackage)) {
-                continue;
+        if (o1.second.mTotalTime != o2.second.mTotalTime) {
+            return o1.second.mTotalTime > o2.second.mTotalTime ? -1 : 1;
+        }
+        if (o1.first.mUid != o2.first.mUid) {
+            return o1.first.mUid < o2.first.mUid ? -1 : 1;
+        }
+        if (o1.first.mProcess != o2.first.mProcess) {
+            int diff = o1.first.mProcess.compareTo(o2.first.mProcess);
+            if (diff != 0) {
+                return diff;
             }
-            pw.print(prefixInner);
+        }
+        return 0;
+    };
+
+    public ArrayList<Pair<SourceKey, SourceDumpContainer>> createSortedAssociations(long now,
+            long totalTime) {
+        final int NSRC = mSources.size();
+        ArrayList<Pair<SourceKey, SourceDumpContainer>> sources = new ArrayList<>(NSRC);
+        for (int isrc = 0; isrc < NSRC; isrc++) {
+            final SourceState src = mSources.valueAt(isrc);
+            final SourceDumpContainer cont = new SourceDumpContainer(src);
+            long duration = src.mDuration;
+            if (src.mNesting > 0) {
+                duration += now - src.mStartUptime;
+            }
+            cont.mTotalTime = duration;
+            cont.mActiveTime = dumpTime(null, null, src, totalTime, now, false, false);
+            if (cont.mActiveTime < 0) {
+                cont.mActiveTime = -cont.mActiveTime;
+            }
+            sources.add(new Pair<>(mSources.keyAt(isrc), cont));
+        }
+        Collections.sort(sources, ASSOCIATION_COMPARATOR);
+        return sources;
+    }
+
+    public void dumpStats(PrintWriter pw, String prefix, String prefixInner, String headerPrefix,
+            ArrayList<Pair<SourceKey, SourceDumpContainer>> sources, long now, long totalTime,
+            String reqPackage, boolean dumpDetails, boolean dumpAll) {
+        final String prefixInnerInner = prefixInner + "     ";
+        long totalDuration = mTotalActiveDuration;
+        if (mTotalActiveNesting > 0) {
+            totalDuration += now - mTotalActiveStartUptime;
+        }
+        if (totalDuration > 0 || mTotalActiveCount != 0) {
+            pw.print(prefix);
+            pw.print("Active count ");
+            pw.print(mTotalActiveCount);
+            if (dumpAll) {
+                pw.print(": ");
+                TimeUtils.formatDuration(totalDuration, pw);
+                pw.print(" / ");
+            } else {
+                pw.print(": time ");
+            }
+            DumpUtils.printPercent(pw, (double) totalDuration / (double) totalTime);
+            pw.println();
+        }
+        if (dumpAll && mTotalActiveNesting != 0) {
+            pw.print(prefix);
+            pw.print("mTotalActiveNesting=");
+            pw.print(mTotalActiveNesting);
+            pw.print(" mTotalActiveStartUptime=");
+            TimeUtils.formatDuration(mTotalActiveStartUptime, now, pw);
+            pw.println();
+        }
+        totalDuration = mTotalDuration;
+        if (mTotalNesting > 0) {
+            totalDuration += now - mTotalStartUptime;
+        }
+        if (totalDuration > 0 || mTotalCount != 0) {
+            pw.print(prefix);
+            pw.print("Total count ");
+            pw.print(mTotalCount);
+            if (dumpAll) {
+                pw.print(": ");
+                TimeUtils.formatDuration(totalDuration, pw);
+                pw.print(" / ");
+            } else {
+                pw.print(": time ");
+            }
+            DumpUtils.printPercent(pw, (double) totalDuration / (double) totalTime);
+            pw.println();
+        }
+        if (dumpAll && mTotalNesting != 0) {
+            pw.print(prefix);
+            pw.print("mTotalNesting=");
+            pw.print(mTotalNesting);
+            pw.print(" mTotalStartUptime=");
+            TimeUtils.formatDuration(mTotalStartUptime, now, pw);
+            pw.println();
+        }
+        final int NSRC = sources.size();
+        for (int isrc = 0; isrc < NSRC; isrc++) {
+            final SourceKey key = sources.get(isrc).first;
+            final SourceDumpContainer cont = sources.get(isrc).second;
+            final SourceState src = cont.mState;
+            pw.print(prefix);
             pw.print("<- ");
             pw.print(key.mProcess);
             pw.print("/");
@@ -496,24 +737,69 @@
                 pw.print(key.mPackage);
                 pw.print(")");
             }
+            // If we are skipping this one, we still print the first line just to give
+            // context for the others (so it is clear the total times for the overall
+            // association come from other sources whose times are not shown).
+            if (reqPackage != null && !reqPackage.equals(key.mProcess)
+                    && !reqPackage.equals(key.mPackage)) {
+                pw.println();
+                continue;
+            }
             pw.println(":");
+            if (src.mActiveCount != 0 || src.mActiveDurations != null || src.mActiveDuration != 0
+                    || src.mActiveStartUptime != 0) {
+                pw.print(prefixInner);
+                pw.print("   Active count ");
+                pw.print(src.mActiveCount);
+                if (dumpDetails) {
+                    if (dumpAll) {
+                        if (src.mActiveDurations != null) {
+                            pw.print(" (multi-state)");
+                        } else if (src.mActiveProcState >= ProcessStats.STATE_PERSISTENT) {
+                            pw.print(" (");
+                            pw.print(DumpUtils.STATE_NAMES[src.mActiveProcState]);
+                            pw.print(")");
+                        } else {
+                            pw.print(" (*UNKNOWN STATE*)");
+                        }
+                    }
+                    if (dumpAll) {
+                        pw.print(": ");
+                        TimeUtils.formatDuration(cont.mActiveTime, pw);
+                        pw.print(" / ");
+                    } else {
+                        pw.print(": time ");
+                    }
+                    DumpUtils.printPercent(pw, (double) cont.mActiveTime / (double) totalTime);
+                    if (src.mActiveStartUptime != 0) {
+                        pw.print(" (running)");
+                    }
+                    pw.println();
+                    if (src.mActiveDurations != null) {
+                        dumpTime(pw, prefixInnerInner, src, totalTime, now, dumpDetails, dumpAll);
+                    }
+                } else {
+                    pw.print(": ");
+                    dumpActiveDurationSummary(pw, src, totalTime, now, dumpAll);
+                }
+            }
             pw.print(prefixInner);
             pw.print("   Total count ");
             pw.print(src.mCount);
-            long duration = src.mDuration;
-            if (src.mNesting > 0) {
-                duration += now - src.mStartUptime;
-            }
             if (dumpAll) {
-                pw.print(": Duration ");
-                TimeUtils.formatDuration(duration, pw);
+                pw.print(": ");
+                TimeUtils.formatDuration(cont.mTotalTime, pw);
                 pw.print(" / ");
             } else {
                 pw.print(": time ");
             }
-            DumpUtils.printPercent(pw, (double)duration/(double)totalTime);
+            DumpUtils.printPercent(pw, (double) cont.mTotalTime / (double) totalTime);
             if (src.mNesting > 0) {
                 pw.print(" (running");
+                if (dumpAll) {
+                    pw.print(" nest=");
+                    pw.print(src.mNesting);
+                }
                 if (src.mProcState != ProcessStats.STATE_NOTHING) {
                     pw.print(" / ");
                     pw.print(DumpUtils.STATE_NAMES[src.mProcState]);
@@ -523,23 +809,6 @@
                 pw.print(")");
             }
             pw.println();
-            if (src.mActiveCount > 0 || src.mDurations != null || src.mActiveDuration != 0
-                    || src.mActiveStartUptime != 0) {
-                pw.print(prefixInner);
-                pw.print("   Active count ");
-                pw.print(src.mActiveCount);
-                if (dumpDetails) {
-                    if (dumpAll) {
-                        pw.print(src.mDurations != null ? " (multi-field)" : " (inline)");
-                    }
-                    pw.println(":");
-                    dumpTime(pw, prefixInner, src, totalTime, now, dumpDetails, dumpAll);
-                } else {
-                    pw.print(": ");
-                    dumpActiveDurationSummary(pw, src, totalTime, now, dumpAll);
-                    pw.println();
-                }
-            }
             if (dumpAll) {
                 if (src.mInTrackingList) {
                     pw.print(prefixInner);
@@ -565,7 +834,6 @@
             duration = -duration;
         }
         if (dumpAll) {
-            pw.print("Duration ");
             TimeUtils.formatDuration(duration, pw);
             pw.print(" / ");
         } else {
@@ -584,10 +852,10 @@
         boolean isRunning = false;
         for (int iprocstate = 0; iprocstate < ProcessStats.STATE_COUNT; iprocstate++) {
             long time;
-            if (src.mDurations != null) {
-                time = src.mDurations.getValueForId((byte)iprocstate);
+            if (src.mActiveDurations != null) {
+                time = src.mActiveDurations.getValueForId((byte) iprocstate);
             } else {
-                time = src.mActiveProcState == iprocstate ? src.mDuration : 0;
+                time = src.mActiveProcState == iprocstate ? src.mActiveDuration : 0;
             }
             final String running;
             if (src.mActiveStartUptime != 0 && src.mActiveProcState == iprocstate) {
@@ -600,11 +868,9 @@
             if (time != 0) {
                 if (pw != null) {
                     pw.print(prefix);
-                    pw.print("  ");
                     pw.print(DumpUtils.STATE_LABELS[iprocstate]);
                     pw.print(": ");
                     if (dumpAll) {
-                        pw.print("Duration ");
                         TimeUtils.formatDuration(time, pw);
                         pw.print(" / ");
                     } else {
@@ -619,21 +885,6 @@
                 totalTime += time;
             }
         }
-        if (totalTime != 0 && pw != null) {
-            pw.print(prefix);
-            pw.print("  ");
-            pw.print(DumpUtils.STATE_LABEL_TOTAL);
-            pw.print(": ");
-            if (dumpAll) {
-                pw.print("Duration ");
-                TimeUtils.formatDuration(totalTime, pw);
-                pw.print(" / ");
-            } else {
-                pw.print("time ");
-            }
-            DumpUtils.printPercent(pw, (double) totalTime / (double) overallTime);
-            pw.println();
-        }
         return isRunning ? -totalTime : totalTime;
     }
 
@@ -667,11 +918,11 @@
             pw.print(",");
             pw.print(src.mActiveCount);
             final long timeNow = src.mActiveStartUptime != 0 ? (now-src.mActiveStartUptime) : 0;
-            if (src.mDurations != null) {
-                final int N = src.mDurations.getKeyCount();
+            if (src.mActiveDurations != null) {
+                final int N = src.mActiveDurations.getKeyCount();
                 for (int i=0; i<N; i++) {
-                    final int dkey = src.mDurations.getKeyAt(i);
-                    duration = src.mDurations.getValue(dkey);
+                    final int dkey = src.mActiveDurations.getKeyAt(i);
+                    duration = src.mActiveDurations.getValue(dkey);
                     if (dkey == src.mActiveProcState) {
                         duration += timeNow;
                     }
@@ -718,11 +969,11 @@
                         src.mActiveCount);
             }
             final long timeNow = src.mActiveStartUptime != 0 ? (now-src.mActiveStartUptime) : 0;
-            if (src.mDurations != null) {
-                final int N = src.mDurations.getKeyCount();
+            if (src.mActiveDurations != null) {
+                final int N = src.mActiveDurations.getKeyCount();
                 for (int i=0; i<N; i++) {
-                    final int dkey = src.mDurations.getKeyAt(i);
-                    duration = src.mDurations.getValue(dkey);
+                    final int dkey = src.mActiveDurations.getKeyAt(i);
+                    duration = src.mActiveDurations.getValue(dkey);
                     if (dkey == src.mActiveProcState) {
                         duration += timeNow;
                     }
diff --git a/core/java/com/android/internal/app/procstats/ProcessStats.java b/core/java/com/android/internal/app/procstats/ProcessStats.java
index 8e88c51..875cff8 100644
--- a/core/java/com/android/internal/app/procstats/ProcessStats.java
+++ b/core/java/com/android/internal/app/procstats/ProcessStats.java
@@ -31,6 +31,7 @@
 import android.util.ArraySet;
 import android.util.DebugUtils;
 import android.util.LongSparseArray;
+import android.util.Pair;
 import android.util.Slog;
 import android.util.SparseArray;
 import android.util.TimeUtils;
@@ -48,6 +49,7 @@
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.Collections;
+import java.util.Comparator;
 import java.util.Objects;
 import java.util.regex.Matcher;
 import java.util.regex.Pattern;
@@ -179,7 +181,7 @@
             {"proc", "pkg-proc", "pkg-svc", "pkg-asc", "pkg-all", "all"};
 
     // Current version of the parcel format.
-    private static final int PARCEL_VERSION = 36;
+    private static final int PARCEL_VERSION = 38;
     // In-memory Parcel magic number, used to detect attempts to unmarshall bad data
     private static final int MAGIC = 0x50535454;
 
@@ -196,6 +198,9 @@
     public int mMemFactor = STATE_NOTHING;
     public long mStartTime;
 
+    // Number of individual stats that have been aggregated to create this one.
+    public int mNumAggregated = 1;
+
     public long mTimePeriodStartClock;
     public long mTimePeriodStartRealtime;
     public long mTimePeriodEndRealtime;
@@ -348,6 +353,8 @@
 
         mSysMemUsage.mergeStats(other.mSysMemUsage);
 
+        mNumAggregated += other.mNumAggregated;
+
         if (other.mTimePeriodStartClock < mTimePeriodStartClock) {
             mTimePeriodStartClock = other.mTimePeriodStartClock;
             mTimePeriodStartClockStr = other.mTimePeriodStartClockStr;
@@ -569,6 +576,7 @@
     }
 
     private void resetCommon() {
+        mNumAggregated = 1;
         mTimePeriodStartClock = System.currentTimeMillis();
         buildTimePeriodStartClockStr();
         mTimePeriodStartRealtime = mTimePeriodEndRealtime = SystemClock.elapsedRealtime();
@@ -845,6 +853,7 @@
             }
         }
 
+        out.writeInt(mNumAggregated);
         out.writeLong(mTimePeriodStartClock);
         out.writeLong(mTimePeriodStartRealtime);
         out.writeLong(mTimePeriodEndRealtime);
@@ -1031,6 +1040,7 @@
 
         mIndexToCommonString = new ArrayList<String>();
 
+        mNumAggregated = in.readInt();
         mTimePeriodStartClock = in.readLong();
         buildTimePeriodStartClockStr();
         mTimePeriodStartRealtime = in.readLong();
@@ -1457,15 +1467,79 @@
         }
     }
 
+    final class AssociationDumpContainer {
+        final AssociationState mState;
+        ArrayList<Pair<AssociationState.SourceKey, AssociationState.SourceDumpContainer>> mSources;
+        long mTotalTime;
+        long mActiveTime;
+
+        AssociationDumpContainer(AssociationState state) {
+            mState = state;
+        }
+    }
+
+    static final Comparator<AssociationDumpContainer> ASSOCIATION_COMPARATOR = (o1, o2) -> {
+        int diff = o1.mState.getProcessName().compareTo(o2.mState.getProcessName());
+        if (diff != 0) {
+            return diff;
+        }
+        if (o1.mActiveTime != o2.mActiveTime) {
+            return o1.mActiveTime > o2.mActiveTime ? -1 : 1;
+        }
+        if (o1.mTotalTime != o2.mTotalTime) {
+            return o1.mTotalTime > o2.mTotalTime ? -1 : 1;
+        }
+        diff = o1.mState.getName().compareTo(o2.mState.getName());
+        if (diff != 0) {
+            return diff;
+        }
+        return 0;
+    };
+
     public void dumpLocked(PrintWriter pw, String reqPackage, long now, boolean dumpSummary,
             boolean dumpDetails, boolean dumpAll, boolean activeOnly, int section) {
         long totalTime = DumpUtils.dumpSingleTime(null, null, mMemFactorDurations, mMemFactor,
                 mStartTime, now);
-        boolean sepNeeded = false;
+        pw.print("          Start time: ");
+        pw.print(DateFormat.format("yyyy-MM-dd HH:mm:ss", mTimePeriodStartClock));
+        pw.println();
+        pw.print("        Total uptime: ");
+        TimeUtils.formatDuration(
+                (mRunning ? SystemClock.uptimeMillis() : mTimePeriodEndUptime)
+                        - mTimePeriodStartUptime, pw);
+        pw.println();
+        pw.print("  Total elapsed time: ");
+        TimeUtils.formatDuration(
+                (mRunning ? SystemClock.elapsedRealtime() : mTimePeriodEndRealtime)
+                        - mTimePeriodStartRealtime, pw);
+        boolean partial = true;
+        if ((mFlags & FLAG_SHUTDOWN) != 0) {
+            pw.print(" (shutdown)");
+            partial = false;
+        }
+        if ((mFlags & FLAG_SYSPROPS) != 0) {
+            pw.print(" (sysprops)");
+            partial = false;
+        }
+        if ((mFlags & FLAG_COMPLETE) != 0) {
+            pw.print(" (complete)");
+            partial = false;
+        }
+        if (partial) {
+            pw.print(" (partial)");
+        }
+        if (mHasSwappedOutPss) {
+            pw.print(" (swapped-out-pss)");
+        }
+        pw.print(' ');
+        pw.print(mRuntime);
+        pw.println();
+        pw.print("     Aggregated over: ");
+        pw.println(mNumAggregated);
         if (mSysMemUsage.getKeyCount() > 0) {
+            pw.println();
             pw.println("System memory usage:");
             mSysMemUsage.dump(pw, "  ", ALL_SCREEN_ADJ, ALL_MEM_ADJ);
-            sepNeeded = true;
         }
         boolean printedHeader = false;
         if ((section & REPORT_PKG_STATS) != 0) {
@@ -1485,8 +1559,8 @@
                         final int NASCS = pkgState.mAssociations.size();
                         final boolean pkgMatch = reqPackage == null || reqPackage.equals(pkgName);
                         boolean onlyAssociations = false;
+                        boolean procMatch = false;
                         if (!pkgMatch) {
-                            boolean procMatch = false;
                             for (int iproc = 0; iproc < NPROCS; iproc++) {
                                 ProcessState proc = pkgState.mProcesses.valueAt(iproc);
                                 if (reqPackage.equals(proc.getName())) {
@@ -1511,10 +1585,9 @@
                         }
                         if (NPROCS > 0 || NSRVS > 0 || NASCS > 0) {
                             if (!printedHeader) {
-                                if (sepNeeded) pw.println();
+                                pw.println();
                                 pw.println("Per-Package Stats:");
                                 printedHeader = true;
-                                sepNeeded = true;
                             }
                             pw.print("  * ");
                             pw.print(pkgName);
@@ -1597,6 +1670,8 @@
                             }
                         }
                         if ((section & REPORT_PKG_ASC_STATS) != 0) {
+                            ArrayList<AssociationDumpContainer> associations =
+                                    new ArrayList<>(NASCS);
                             for (int iasc = 0; iasc < NASCS; iasc++) {
                                 AssociationState asc = pkgState.mAssociations.valueAt(iasc);
                                 if (!pkgMatch && !reqPackage.equals(asc.getProcessName())) {
@@ -1604,6 +1679,18 @@
                                         continue;
                                     }
                                 }
+                                final AssociationDumpContainer cont =
+                                        new AssociationDumpContainer(asc);
+                                cont.mSources = asc.createSortedAssociations(now, totalTime);
+                                cont.mTotalTime = asc.getTotalDuration(now);
+                                cont.mActiveTime = asc.getActiveDuration(now);
+                                associations.add(cont);
+                            }
+                            Collections.sort(associations, ASSOCIATION_COMPARATOR);
+                            final int NCONT = associations.size();
+                            for (int iasc = 0; iasc < NCONT; iasc++) {
+                                final AssociationDumpContainer cont = associations.get(iasc);
+                                final AssociationState asc = cont.mState;
                                 if (activeOnly && !asc.isInUse()) {
                                     pw.print("      (Not active association: ");
                                     pw.print(pkgState.mAssociations.keyAt(iasc));
@@ -1615,13 +1702,15 @@
                                 } else {
                                     pw.print("      * Asc ");
                                 }
-                                pw.print(pkgState.mAssociations.keyAt(iasc));
+                                pw.print(cont.mState.getName());
                                 pw.println(":");
                                 pw.print("        Process: ");
                                 pw.println(asc.getProcessName());
                                 asc.dumpStats(pw, "        ", "          ", "    ",
-                                        now, totalTime, onlyAssociations ? reqPackage : null,
-                                        dumpDetails, dumpAll);
+                                        cont.mSources, now, totalTime,
+                                        onlyAssociations && !pkgMatch && !procMatch
+                                                && !asc.getProcessName().equals(reqPackage)
+                                                ? reqPackage : null, dumpDetails, dumpAll);
                             }
                         }
                     }
@@ -1651,10 +1740,7 @@
                         continue;
                     }
                     numShownProcs++;
-                    if (sepNeeded) {
-                        pw.println();
-                    }
-                    sepNeeded = true;
+                    pw.println();
                     if (!printedHeader) {
                         pw.println("Multi-Package Common Processes:");
                         printedHeader = true;
@@ -1684,11 +1770,7 @@
         }
 
         if (dumpAll) {
-            if (sepNeeded) {
-                pw.println();
-            }
-            sepNeeded = true;
-
+            pw.println();
             if (mTrackingAssociations.size() > 0) {
                 pw.println();
                 pw.println("Tracking associations:");
@@ -1734,9 +1816,7 @@
             }
         }
 
-        if (sepNeeded) {
-            pw.println();
-        }
+        pw.println();
         if (dumpSummary) {
             pw.println("Process summary:");
             dumpSummaryLocked(pw, reqPackage, now, activeOnly);
@@ -1861,41 +1941,6 @@
         pw.print("x over ");
         TimeUtils.formatDuration(mExternalSlowPssTime, pw);
         pw.println();
-        pw.println();
-        pw.print("          Start time: ");
-        pw.print(DateFormat.format("yyyy-MM-dd HH:mm:ss", mTimePeriodStartClock));
-        pw.println();
-        pw.print("        Total uptime: ");
-        TimeUtils.formatDuration(
-                (mRunning ? SystemClock.uptimeMillis() : mTimePeriodEndUptime)
-                        - mTimePeriodStartUptime, pw);
-        pw.println();
-        pw.print("  Total elapsed time: ");
-        TimeUtils.formatDuration(
-                (mRunning ? SystemClock.elapsedRealtime() : mTimePeriodEndRealtime)
-                        - mTimePeriodStartRealtime, pw);
-        boolean partial = true;
-        if ((mFlags&FLAG_SHUTDOWN) != 0) {
-            pw.print(" (shutdown)");
-            partial = false;
-        }
-        if ((mFlags&FLAG_SYSPROPS) != 0) {
-            pw.print(" (sysprops)");
-            partial = false;
-        }
-        if ((mFlags&FLAG_COMPLETE) != 0) {
-            pw.print(" (complete)");
-            partial = false;
-        }
-        if (partial) {
-            pw.print(" (partial)");
-        }
-        if (mHasSwappedOutPss) {
-            pw.print(" (swapped-out-pss)");
-        }
-        pw.print(' ');
-        pw.print(mRuntime);
-        pw.println();
     }
 
     void dumpFilteredSummaryLocked(PrintWriter pw, String header, String prefix, String prcLabel,
diff --git a/core/java/com/android/internal/compat/ChangeReporter.java b/core/java/com/android/internal/compat/ChangeReporter.java
index 8283eb7..72b0ad7 100644
--- a/core/java/com/android/internal/compat/ChangeReporter.java
+++ b/core/java/com/android/internal/compat/ChangeReporter.java
@@ -22,7 +22,9 @@
 
 import com.android.internal.annotations.GuardedBy;
 
+import java.util.HashMap;
 import java.util.HashSet;
+import java.util.Map;
 import java.util.Objects;
 import java.util.Set;
 
@@ -36,12 +38,10 @@
     private int mSource;
 
     private final class ChangeReport {
-        int mUid;
         long mChangeId;
         int mState;
 
-        ChangeReport(int uid, long changeId, int state) {
-            mUid = uid;
+        ChangeReport(long changeId, int state) {
             mChangeId = changeId;
             mState = state;
         }
@@ -51,40 +51,62 @@
             if (this == o) return true;
             if (o == null || getClass() != o.getClass()) return false;
             ChangeReport that = (ChangeReport) o;
-            return mUid == that.mUid
-                    && mChangeId == that.mChangeId
+            return mChangeId == that.mChangeId
                     && mState == that.mState;
         }
 
         @Override
         public int hashCode() {
-            return Objects.hash(mUid, mChangeId, mState);
+            return Objects.hash(mChangeId, mState);
         }
     }
 
+    // Maps uid to a set of ChangeReports (that were reported for that uid).
     @GuardedBy("mReportedChanges")
-    private Set<ChangeReport> mReportedChanges =  new HashSet<>();
+    private final Map<Integer, Set<ChangeReport>> mReportedChanges;
 
     public ChangeReporter(int source) {
         mSource = source;
+        mReportedChanges =  new HashMap<>();
     }
 
     /**
-     * Report the change to stats log.
+     * Report the change to stats log and to the debug log if the change was not previously
+     * logged already.
      *
      * @param uid      affected by the change
      * @param changeId the reported change id
      * @param state    of the reported change - enabled/disabled/only logged
      */
     public void reportChange(int uid, long changeId, int state) {
-        ChangeReport report = new ChangeReport(uid, changeId, state);
+        ChangeReport report = new ChangeReport(changeId, state);
         synchronized (mReportedChanges) {
-            if (!mReportedChanges.contains(report)) {
+            Set<ChangeReport> reportedChangesForUid = mReportedChanges.get(uid);
+            if (reportedChangesForUid == null) {
+                mReportedChanges.put(uid, new HashSet<ChangeReport>());
+                reportedChangesForUid = mReportedChanges.get(uid);
+            }
+            if (!reportedChangesForUid.contains(report)) {
                 debugLog(uid, changeId, state);
                 StatsLog.write(StatsLog.APP_COMPATIBILITY_CHANGE_REPORTED, uid, changeId,
                         state, mSource);
-                mReportedChanges.add(report);
+                reportedChangesForUid.add(report);
             }
+
+        }
+    }
+
+    /**
+     * Clears the saved information about a given uid. Requests to report uid again will be reported
+     * regardless to the past reports.
+     *
+     * <p> Only intended to be called from PlatformCompat.
+     *
+     * @param uid to reset
+     */
+    public void resetReportedChanges(int uid) {
+        synchronized (mReportedChanges) {
+            mReportedChanges.remove(uid);
         }
     }
 
diff --git a/core/java/android/hardware/biometrics/IBiometricConfirmDeviceCredentialCallback.aidl b/core/java/com/android/internal/compat/CompatibilityChangeConfig.aidl
similarity index 68%
copy from core/java/android/hardware/biometrics/IBiometricConfirmDeviceCredentialCallback.aidl
copy to core/java/com/android/internal/compat/CompatibilityChangeConfig.aidl
index 8b35852..434c1b8 100644
--- a/core/java/android/hardware/biometrics/IBiometricConfirmDeviceCredentialCallback.aidl
+++ b/core/java/com/android/internal/compat/CompatibilityChangeConfig.aidl
@@ -14,13 +14,6 @@
  * limitations under the License.
  */
 
-package android.hardware.biometrics;
+package com.android.internal.compat;
 
-/**
- * Communication channel between ConfirmDeviceCredential / ConfirmLock* and BiometricService.
- * @hide
- */
-interface IBiometricConfirmDeviceCredentialCallback {
-    // Invoked when authentication should be canceled.
-    oneway void cancel();
-}
\ No newline at end of file
+parcelable CompatibilityChangeConfig;
diff --git a/core/java/com/android/internal/compat/CompatibilityChangeConfig.java b/core/java/com/android/internal/compat/CompatibilityChangeConfig.java
new file mode 100644
index 0000000..fd2ada0
--- /dev/null
+++ b/core/java/com/android/internal/compat/CompatibilityChangeConfig.java
@@ -0,0 +1,95 @@
+/*
+ * 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.compat;
+
+
+import android.compat.Compatibility.ChangeConfig;
+import android.os.Parcel;
+import android.os.Parcelable;
+
+import java.util.HashSet;
+import java.util.Set;
+
+/**
+ * Parcelable containing compat config overrides for a given application.
+ * @hide
+ */
+public final class CompatibilityChangeConfig implements Parcelable {
+    private final ChangeConfig mChangeConfig;
+
+    public CompatibilityChangeConfig(ChangeConfig changeConfig) {
+        mChangeConfig = changeConfig;
+    }
+
+    /**
+     * Changes forced to be enabled.
+     */
+    public Set<Long> enabledChanges() {
+        return mChangeConfig.forceEnabledSet();
+    }
+
+    /**
+     * Changes forced to be disabled.
+     */
+    public Set<Long> disabledChanges() {
+        return mChangeConfig.forceDisabledSet();
+    }
+
+    private CompatibilityChangeConfig(Parcel in) {
+        long[] enabledArray = in.createLongArray();
+        long[] disabledArray = in.createLongArray();
+        Set<Long> enabled = toLongSet(enabledArray);
+        Set<Long> disabled = toLongSet(disabledArray);
+        mChangeConfig = new ChangeConfig(enabled, disabled);
+    }
+
+    private static Set<Long> toLongSet(long[] values) {
+        Set<Long> ret = new HashSet<>();
+        for (long value: values) {
+            ret.add(value);
+        }
+        return ret;
+    }
+
+    @Override
+    public int describeContents() {
+        return 0;
+    }
+
+    @Override
+    public void writeToParcel(Parcel dest, int flags) {
+        long[] enabled = mChangeConfig.forceEnabledChangesArray();
+        long[] disabled = mChangeConfig.forceDisabledChangesArray();
+
+        dest.writeLongArray(enabled);
+        dest.writeLongArray(disabled);
+    }
+
+    public static final Parcelable.Creator<CompatibilityChangeConfig> CREATOR =
+            new Parcelable.Creator<CompatibilityChangeConfig>() {
+
+                @Override
+                public CompatibilityChangeConfig createFromParcel(Parcel in) {
+                    return new CompatibilityChangeConfig(in);
+                }
+
+                @Override
+                public CompatibilityChangeConfig[] newArray(int size) {
+                    return new CompatibilityChangeConfig[size];
+                }
+            };
+}
diff --git a/core/java/com/android/internal/compat/IPlatformCompat.aidl b/core/java/com/android/internal/compat/IPlatformCompat.aidl
index e415b41..4099cfa 100644
--- a/core/java/com/android/internal/compat/IPlatformCompat.aidl
+++ b/core/java/com/android/internal/compat/IPlatformCompat.aidl
@@ -18,6 +18,8 @@
 
 import android.content.pm.ApplicationInfo;
 
+parcelable CompatibilityChangeConfig;
+
 /**
  * Platform private API for talking with the PlatformCompat service.
  *
@@ -43,11 +45,6 @@
     /**
      * Reports that a compatibility change is affecting an app process now.
      *
-     * <p>Same as {@link #reportChange(long, ApplicationInfo)}, except it receives a package name
-     * instead of an {@link ApplicationInfo}
-     * object, and finds an app info object based on the package name. Returns {@code true} if
-     * there is no installed package by that name.
-     *
      * <p>Note: for changes that are gated using {@link #isChangeEnabled(long, String)},
      * you do not need to call this API directly. The change will be reported for you.
      *
@@ -57,6 +54,17 @@
      void reportChangeByPackageName(long changeId, in String packageName);
 
     /**
+     * Reports that a compatibility change is affecting an app process now.
+     *
+     * <p>Note: for changes that are gated using {@link #isChangeEnabled(long, int)},
+     * you do not need to call this API directly. The change will be reported for you.
+     *
+     * @param changeId The ID of the compatibility change taking effect.
+     * @param uid      The UID of the app in question.
+     */
+    void reportChangeByUid(long changeId, int uid);
+
+    /**
      * Query if a given compatibility change is enabled for an app process. This method should
      * be called when implementing functionality on behalf of the affected app.
      *
@@ -95,4 +103,45 @@
      * @return {@code true} if the change is enabled for the current app.
      */
     boolean isChangeEnabledByPackageName(long changeId, in String packageName);
-}
\ No newline at end of file
+
+    /**
+     * Query if a given compatibility change is enabled for an app process. This method should
+     * be called when implementing functionality on behalf of the affected app.
+     *
+     * <p>Same as {@link #isChangeEnabled(long, ApplicationInfo)}, except it receives a uid
+     * instead of an {@link ApplicationInfo} object, and finds an app info object based on the
+     * uid (or objects if there's more than one package associated with the UID).
+     * Returns {@code true} if there are no installed packages for the required UID, or if the
+     * change is enabled for ALL of the installed packages associated with the provided UID. Please
+     * use a more specific API if you want a different behaviour for multi-package UIDs.
+     *
+     * <p>If this method returns {@code true}, the calling code should implement the compatibility
+     * change, resulting in differing behaviour compared to earlier releases. If this method
+     * returns {@code false}, the calling code should behave as it did in earlier releases.
+     *
+     * <p>It will also report the change as {@link #reportChange(long, int)} would, so there is
+     * no need to call that method directly.
+     *
+     * @param changeId The ID of the compatibility change in question.
+     * @param uid      The UID of the app in question.
+     * @return {@code true} if the change is enabled for the current app.
+     */
+    boolean isChangeEnabledByUid(long changeId, int uid);
+
+    /**
+     * Add overrides to compatibility changes.
+     *
+     * @param overrides Parcelable containing the compat change overrides to be applied.
+     * @param packageName The package name of the app whose changes will be overridden.
+     *
+     */
+    void setOverrides(in CompatibilityChangeConfig overrides, in String packageName);
+
+    /**
+     * Revert overrides to compatibility changes.
+     *
+     * @param packageName The package name of the app whose overrides will be cleared.
+     *
+     */
+    void clearOverrides(in String packageName);
+}
diff --git a/core/java/com/android/internal/compat/OWNERS b/core/java/com/android/internal/compat/OWNERS
new file mode 100644
index 0000000..2b7cdb0
--- /dev/null
+++ b/core/java/com/android/internal/compat/OWNERS
@@ -0,0 +1,7 @@
+# Use this reviewer by default.
+platform-compat-eng+reviews@google.com
+
+andreionea@google.com
+atrost@google.com
+mathewi@google.com
+satayev@google.com
diff --git a/core/java/com/android/internal/config/sysui/SystemUiDeviceConfigFlags.java b/core/java/com/android/internal/config/sysui/SystemUiDeviceConfigFlags.java
index 5142d3c..033e9b2 100644
--- a/core/java/com/android/internal/config/sysui/SystemUiDeviceConfigFlags.java
+++ b/core/java/com/android/internal/config/sysui/SystemUiDeviceConfigFlags.java
@@ -239,6 +239,13 @@
     public static final String ASSIST_TRANSCRIPTION_MIN_DURATION =
             "assist_transcription_min_duration";
 
+    /**
+     * (boolean) Whether or not to enable an extra section in the notification shade which
+     * filters for "people" related messages.
+     */
+    public static final String NOTIFICATIONS_USE_PEOPLE_FILTERING =
+            "notifications_use_people_filtering";
+
     // Flags related to brightline falsing
 
     /**
diff --git a/core/java/com/android/internal/os/KernelWakelockReader.java b/core/java/com/android/internal/os/KernelWakelockReader.java
index e09e0e6..cffb0ad 100644
--- a/core/java/com/android/internal/os/KernelWakelockReader.java
+++ b/core/java/com/android/internal/os/KernelWakelockReader.java
@@ -29,6 +29,7 @@
 
 import java.io.File;
 import java.io.FileInputStream;
+import java.util.Arrays;
 import java.util.Iterator;
 
 /**
@@ -66,6 +67,7 @@
     private final String[] mProcWakelocksName = new String[3];
     private final long[] mProcWakelocksData = new long[3];
     private ISuspendControlService mSuspendControlService = null;
+    private byte[] mKernelWakelockBuffer = new byte[32 * 1024];
 
     /**
      * Reads kernel wakelock stats and updates the staleStats with the new information.
@@ -84,7 +86,7 @@
             }
             return removeOldStats(staleStats);
         } else {
-            byte[] buffer = new byte[32*1024];
+            Arrays.fill(mKernelWakelockBuffer, (byte) 0);
             int len = 0;
             boolean wakeup_sources;
             final long startTime = SystemClock.uptimeMillis();
@@ -107,7 +109,8 @@
                 }
 
                 int cnt;
-                while ((cnt = is.read(buffer, len, buffer.length - len)) > 0) {
+                while ((cnt = is.read(mKernelWakelockBuffer, len,
+                                mKernelWakelockBuffer.length - len)) > 0) {
                     len += cnt;
                 }
 
@@ -125,12 +128,13 @@
             }
 
             if (len > 0) {
-                if (len >= buffer.length) {
-                    Slog.wtf(TAG, "Kernel wake locks exceeded buffer size " + buffer.length);
+                if (len >= mKernelWakelockBuffer.length) {
+                    Slog.wtf(TAG, "Kernel wake locks exceeded mKernelWakelockBuffer size "
+                            + mKernelWakelockBuffer.length);
                 }
                 int i;
                 for (i=0; i<len; i++) {
-                    if (buffer[i] == '\0') {
+                    if (mKernelWakelockBuffer[i] == '\0') {
                         len = i;
                         break;
                     }
@@ -143,7 +147,7 @@
                 Slog.w(TAG, "Failed to get Native wakelock stats from SystemSuspend");
             }
             // Get kernel wakelock stats
-            parseProcWakelocks(buffer, len, wakeup_sources, staleStats);
+            parseProcWakelocks(mKernelWakelockBuffer, len, wakeup_sources, staleStats);
             return removeOldStats(staleStats);
         }
     }
diff --git a/core/java/com/android/internal/os/RuntimeInit.java b/core/java/com/android/internal/os/RuntimeInit.java
index 9fff447..fd3cd42 100644
--- a/core/java/com/android/internal/os/RuntimeInit.java
+++ b/core/java/com/android/internal/os/RuntimeInit.java
@@ -35,7 +35,7 @@
 import dalvik.system.RuntimeHooks;
 import dalvik.system.VMRuntime;
 
-import libcore.net.MimeMap;
+import libcore.content.type.MimeMap;
 
 import java.lang.reflect.InvocationTargetException;
 import java.lang.reflect.Method;
@@ -203,13 +203,15 @@
     public static void preForkInit() {
         if (DEBUG) Slog.d(TAG, "Entered preForkInit.");
         RuntimeInit.enableDdms();
+        // TODO(b/142019040#comment13): Decide whether to load the default instance eagerly, i.e.
+        // MimeMap.setDefault(DefaultMimeMapFactory.create());
         /*
          * Replace libcore's minimal default mapping between MIME types and file
          * extensions with a mapping that's suitable for Android. Android's mapping
          * contains many more entries that are derived from IANA registrations but
          * with several customizations (extensions, overrides).
          */
-        MimeMap.setDefault(DefaultMimeMapFactory.create());
+        MimeMap.setDefaultSupplier(DefaultMimeMapFactory::create);
     }
 
     @UnsupportedAppUsage
diff --git a/core/java/com/android/internal/os/ZygoteConnection.java b/core/java/com/android/internal/os/ZygoteConnection.java
index b3ec5f5..a14b093 100644
--- a/core/java/com/android/internal/os/ZygoteConnection.java
+++ b/core/java/com/android/internal/os/ZygoteConnection.java
@@ -306,6 +306,12 @@
     }
 
     private void handleBootCompleted() {
+        try {
+            mSocketOutStream.writeInt(0);
+        } catch (IOException ioe) {
+            throw new IllegalStateException("Error writing to command socket", ioe);
+        }
+
         VMRuntime.bootCompleted();
     }
 
diff --git a/core/java/com/android/internal/statusbar/IStatusBar.aidl b/core/java/com/android/internal/statusbar/IStatusBar.aidl
index 9441825..c8ba52a 100644
--- a/core/java/com/android/internal/statusbar/IStatusBar.aidl
+++ b/core/java/com/android/internal/statusbar/IStatusBar.aidl
@@ -151,17 +151,17 @@
 
     void showShutdownUi(boolean isReboot, String reason);
 
-    // Used to show the dialog when BiometricService starts authentication
-    void showBiometricDialog(in Bundle bundle, IBiometricServiceReceiverInternal receiver, int type,
-            boolean requireConfirmation, int userId, String opPackageName);
-    // Used to hide the dialog when a biometric is authenticated
+    // Used to show the authentication dialog (Biometrics, Device Credential)
+    void showAuthenticationDialog(in Bundle bundle, IBiometricServiceReceiverInternal receiver,
+            int biometricModality, boolean requireConfirmation, int userId, String opPackageName);
+    // Used to notify the authentication dialog that a biometric has been authenticated or rejected
     void onBiometricAuthenticated(boolean authenticated, String failureReason);
     // Used to set a temporary message, e.g. fingerprint not recognized, finger moved too fast, etc
     void onBiometricHelp(String message);
     // Used to set a message - the dialog will dismiss after a certain amount of time
-    void onBiometricError(String error);
-    // Used to hide the biometric dialog when the AuthenticationClient is stopped
-    void hideBiometricDialog();
+    void onBiometricError(int errorCode, String error);
+    // Used to hide the authentication dialog, e.g. when the application cancels authentication
+    void hideAuthenticationDialog();
 
     /**
      * Notifies System UI that the display is ready to show system decorations.
diff --git a/core/java/com/android/internal/statusbar/IStatusBarService.aidl b/core/java/com/android/internal/statusbar/IStatusBarService.aidl
index 4c3a177..a845b58 100644
--- a/core/java/com/android/internal/statusbar/IStatusBarService.aidl
+++ b/core/java/com/android/internal/statusbar/IStatusBarService.aidl
@@ -99,15 +99,15 @@
     void showPinningEnterExitToast(boolean entering);
     void showPinningEscapeToast();
 
-    // Used to show the dialog when BiometricService starts authentication
-    void showBiometricDialog(in Bundle bundle, IBiometricServiceReceiverInternal receiver, int type,
-            boolean requireConfirmation, int userId, String opPackageName);
-    // Used to hide the dialog when a biometric is authenticated
+    // Used to show the authentication dialog (Biometrics, Device Credential)
+    void showAuthenticationDialog(in Bundle bundle, IBiometricServiceReceiverInternal receiver,
+            int biometricModality, boolean requireConfirmation, int userId, String opPackageName);
+    // Used to notify the authentication dialog that a biometric has been authenticated or rejected
     void onBiometricAuthenticated(boolean authenticated, String failureReason);
     // Used to set a temporary message, e.g. fingerprint not recognized, finger moved too fast, etc
     void onBiometricHelp(String message);
     // Used to set a message - the dialog will dismiss after a certain amount of time
-    void onBiometricError(String error);
-    // Used to hide the biometric dialog when the AuthenticationClient is stopped
-    void hideBiometricDialog();
+    void onBiometricError(int errorCode, String error);
+    // Used to hide the authentication dialog, e.g. when the application cancels authentication
+    void hideAuthenticationDialog();
 }
diff --git a/core/java/com/android/internal/util/MimeIconUtils.java b/core/java/com/android/internal/util/MimeIconUtils.java
index 2230c31..31ea5b2 100644
--- a/core/java/com/android/internal/util/MimeIconUtils.java
+++ b/core/java/com/android/internal/util/MimeIconUtils.java
@@ -27,7 +27,7 @@
 import com.android.internal.R;
 import com.android.internal.annotations.GuardedBy;
 
-import libcore.net.MimeMap;
+import libcore.content.type.MimeMap;
 
 import java.util.Locale;
 import java.util.Objects;
diff --git a/core/java/android/hardware/biometrics/IBiometricConfirmDeviceCredentialCallback.aidl b/core/java/com/android/internal/util/function/DecConsumer.java
similarity index 69%
copy from core/java/android/hardware/biometrics/IBiometricConfirmDeviceCredentialCallback.aidl
copy to core/java/com/android/internal/util/function/DecConsumer.java
index 8b35852..0abb785 100644
--- a/core/java/android/hardware/biometrics/IBiometricConfirmDeviceCredentialCallback.aidl
+++ b/core/java/com/android/internal/util/function/DecConsumer.java
@@ -14,13 +14,15 @@
  * limitations under the License.
  */
 
-package android.hardware.biometrics;
+package com.android.internal.util.function;
+
+import java.util.function.Consumer;
 
 /**
- * Communication channel between ConfirmDeviceCredential / ConfirmLock* and BiometricService.
+ * A 10-argument {@link Consumer}
+ *
  * @hide
  */
-interface IBiometricConfirmDeviceCredentialCallback {
-    // Invoked when authentication should be canceled.
-    oneway void cancel();
-}
\ No newline at end of file
+public interface DecConsumer<A, B, C, D, E, F, G, H, I, J> {
+    void accept(A a, B b, C c, D d, E e, F f, G g, H h, I i, J j);
+}
diff --git a/core/java/android/hardware/biometrics/IBiometricConfirmDeviceCredentialCallback.aidl b/core/java/com/android/internal/util/function/DecFunction.java
similarity index 69%
copy from core/java/android/hardware/biometrics/IBiometricConfirmDeviceCredentialCallback.aidl
copy to core/java/com/android/internal/util/function/DecFunction.java
index 8b35852..59fc5e6 100644
--- a/core/java/android/hardware/biometrics/IBiometricConfirmDeviceCredentialCallback.aidl
+++ b/core/java/com/android/internal/util/function/DecFunction.java
@@ -14,13 +14,15 @@
  * limitations under the License.
  */
 
-package android.hardware.biometrics;
+package com.android.internal.util.function;
+
+import java.util.function.Function;
 
 /**
- * Communication channel between ConfirmDeviceCredential / ConfirmLock* and BiometricService.
+ * A 10-argument {@link Function}
+ *
  * @hide
  */
-interface IBiometricConfirmDeviceCredentialCallback {
-    // Invoked when authentication should be canceled.
-    oneway void cancel();
-}
\ No newline at end of file
+public interface DecFunction<A, B, C, D, E, F, G, H, I, J, R> {
+    R apply(A a, B b, C c, D d, E e, F f, G g, H h, I i, J j);
+}
diff --git a/core/java/android/hardware/biometrics/IBiometricConfirmDeviceCredentialCallback.aidl b/core/java/com/android/internal/util/function/DecPredicate.java
similarity index 69%
copy from core/java/android/hardware/biometrics/IBiometricConfirmDeviceCredentialCallback.aidl
copy to core/java/com/android/internal/util/function/DecPredicate.java
index 8b35852..975993d 100644
--- a/core/java/android/hardware/biometrics/IBiometricConfirmDeviceCredentialCallback.aidl
+++ b/core/java/com/android/internal/util/function/DecPredicate.java
@@ -14,13 +14,15 @@
  * limitations under the License.
  */
 
-package android.hardware.biometrics;
+package com.android.internal.util.function;
+
+import java.util.function.Predicate;
 
 /**
- * Communication channel between ConfirmDeviceCredential / ConfirmLock* and BiometricService.
+ * A 10-argument {@link Predicate}
+ *
  * @hide
  */
-interface IBiometricConfirmDeviceCredentialCallback {
-    // Invoked when authentication should be canceled.
-    oneway void cancel();
-}
\ No newline at end of file
+public interface DecPredicate<A, B, C, D, E, F, G, H, I, J> {
+    boolean test(A a, B b, C c, D d, E e, F f, G g, H h, I i, J j);
+}
diff --git a/core/java/android/hardware/biometrics/IBiometricConfirmDeviceCredentialCallback.aidl b/core/java/com/android/internal/util/function/UndecConsumer.java
similarity index 69%
copy from core/java/android/hardware/biometrics/IBiometricConfirmDeviceCredentialCallback.aidl
copy to core/java/com/android/internal/util/function/UndecConsumer.java
index 8b35852..1a1d4ca 100644
--- a/core/java/android/hardware/biometrics/IBiometricConfirmDeviceCredentialCallback.aidl
+++ b/core/java/com/android/internal/util/function/UndecConsumer.java
@@ -14,13 +14,15 @@
  * limitations under the License.
  */
 
-package android.hardware.biometrics;
+package com.android.internal.util.function;
+
+import java.util.function.Consumer;
 
 /**
- * Communication channel between ConfirmDeviceCredential / ConfirmLock* and BiometricService.
+ * A 11-argument {@link Consumer}
+ *
  * @hide
  */
-interface IBiometricConfirmDeviceCredentialCallback {
-    // Invoked when authentication should be canceled.
-    oneway void cancel();
-}
\ No newline at end of file
+public interface UndecConsumer<A, B, C, D, E, F, G, H, I, J, K> {
+    void accept(A a, B b, C c, D d, E e, F f, G g, H h, I i, J j, K k);
+}
diff --git a/core/java/android/hardware/biometrics/IBiometricConfirmDeviceCredentialCallback.aidl b/core/java/com/android/internal/util/function/UndecFunction.java
similarity index 69%
rename from core/java/android/hardware/biometrics/IBiometricConfirmDeviceCredentialCallback.aidl
rename to core/java/com/android/internal/util/function/UndecFunction.java
index 8b35852..5cd324c 100644
--- a/core/java/android/hardware/biometrics/IBiometricConfirmDeviceCredentialCallback.aidl
+++ b/core/java/com/android/internal/util/function/UndecFunction.java
@@ -14,13 +14,15 @@
  * limitations under the License.
  */
 
-package android.hardware.biometrics;
+package com.android.internal.util.function;
+
+import java.util.function.Function;
 
 /**
- * Communication channel between ConfirmDeviceCredential / ConfirmLock* and BiometricService.
+ * A 11-argument {@link Function}
+ *
  * @hide
  */
-interface IBiometricConfirmDeviceCredentialCallback {
-    // Invoked when authentication should be canceled.
-    oneway void cancel();
-}
\ No newline at end of file
+public interface UndecFunction<A, B, C, D, E, F, G, H, I, J, K, R> {
+    R apply(A a, B b, C c, D d, E e, F f, G g, H h, I i, J j, K k);
+}
diff --git a/core/java/android/hardware/biometrics/IBiometricConfirmDeviceCredentialCallback.aidl b/core/java/com/android/internal/util/function/UndecPredicate.java
similarity index 69%
copy from core/java/android/hardware/biometrics/IBiometricConfirmDeviceCredentialCallback.aidl
copy to core/java/com/android/internal/util/function/UndecPredicate.java
index 8b35852..c09193e 100644
--- a/core/java/android/hardware/biometrics/IBiometricConfirmDeviceCredentialCallback.aidl
+++ b/core/java/com/android/internal/util/function/UndecPredicate.java
@@ -14,13 +14,15 @@
  * limitations under the License.
  */
 
-package android.hardware.biometrics;
+package com.android.internal.util.function;
+
+import java.util.function.Predicate;
 
 /**
- * Communication channel between ConfirmDeviceCredential / ConfirmLock* and BiometricService.
+ * A 11-argument {@link Predicate}
+ *
  * @hide
  */
-interface IBiometricConfirmDeviceCredentialCallback {
-    // Invoked when authentication should be canceled.
-    oneway void cancel();
-}
\ No newline at end of file
+public interface UndecPredicate<A, B, C, D, E, F, G, H, I, J, K> {
+    boolean test(A a, B b, C c, D d, E e, F f, G g, H h, I i, J j, K k);
+}
diff --git a/core/java/com/android/internal/util/function/pooled/OmniFunction.java b/core/java/com/android/internal/util/function/pooled/OmniFunction.java
index d74e715..7a17253 100755
--- a/core/java/com/android/internal/util/function/pooled/OmniFunction.java
+++ b/core/java/com/android/internal/util/function/pooled/OmniFunction.java
@@ -18,6 +18,8 @@
 
 import com.android.internal.util.FunctionalUtils.ThrowingRunnable;
 import com.android.internal.util.FunctionalUtils.ThrowingSupplier;
+import com.android.internal.util.function.DecConsumer;
+import com.android.internal.util.function.DecFunction;
 import com.android.internal.util.function.HeptConsumer;
 import com.android.internal.util.function.HeptFunction;
 import com.android.internal.util.function.HexConsumer;
@@ -32,6 +34,8 @@
 import com.android.internal.util.function.QuintFunction;
 import com.android.internal.util.function.TriConsumer;
 import com.android.internal.util.function.TriFunction;
+import com.android.internal.util.function.UndecConsumer;
+import com.android.internal.util.function.UndecFunction;
 
 import java.util.function.BiConsumer;
 import java.util.function.BiFunction;
@@ -43,62 +47,65 @@
  *
  * @hide
  */
-abstract class OmniFunction<A, B, C, D, E, F, G, H, I, R> implements
+abstract class OmniFunction<A, B, C, D, E, F, G, H, I, J, K, R> implements
         PooledFunction<A, R>, BiFunction<A, B, R>, TriFunction<A, B, C, R>,
         QuadFunction<A, B, C, D, R>, QuintFunction<A, B, C, D, E, R>,
         HexFunction<A, B, C, D, E, F, R>, HeptFunction<A, B, C, D, E, F, G, R>,
         OctFunction<A, B, C, D, E, F, G, H, R>, NonaFunction<A, B, C, D, E, F, G, H, I, R>,
+        DecFunction<A, B, C, D, E, F, G, H, I, J, R>,
+        UndecFunction<A, B, C, D, E, F, G, H, I, J, K, R>,
         PooledConsumer<A>, BiConsumer<A, B>, TriConsumer<A, B, C>, QuadConsumer<A, B, C, D>,
         QuintConsumer<A, B, C, D, E>, HexConsumer<A, B, C, D, E, F>,
         HeptConsumer<A, B, C, D, E, F, G>, OctConsumer<A, B, C, D, E, F, G, H>,
-        NonaConsumer<A, B, C, D, E, F, G, H, I>, PooledPredicate<A>, BiPredicate<A, B>,
-        PooledSupplier<R>, PooledRunnable, ThrowingRunnable, ThrowingSupplier<R>,
-        PooledSupplier.OfInt, PooledSupplier.OfLong, PooledSupplier.OfDouble {
+        NonaConsumer<A, B, C, D, E, F, G, H, I>, DecConsumer<A, B, C, D, E, F, G, H, I, J>,
+        UndecConsumer<A, B, C, D, E, F, G, H, I, J, K>,
+        PooledPredicate<A>, BiPredicate<A, B>, PooledSupplier<R>, PooledRunnable, ThrowingRunnable,
+        ThrowingSupplier<R>, PooledSupplier.OfInt, PooledSupplier.OfLong, PooledSupplier.OfDouble {
 
-    abstract R invoke(A a, B b, C c, D d, E e, F f, G g, H h, I i);
+    abstract R invoke(A a, B b, C c, D d, E e, F f, G g, H h, I i, J j, K k);
 
     @Override
     public R apply(A o, B o2) {
-        return invoke(o, o2, null, null, null, null, null, null, null);
+        return invoke(o, o2, null, null, null, null, null, null, null, null, null);
     }
 
     @Override
     public R apply(A o) {
-        return invoke(o, null, null, null, null, null, null, null, null);
+        return invoke(o, null, null, null, null, null, null, null, null, null, null);
     }
 
-    public abstract <V> OmniFunction<A, B, C, D, E, F, G, H, I, V> andThen(
+    public abstract <V> OmniFunction<A, B, C, D, E, F, G, H, I, J, K, V> andThen(
             Function<? super R, ? extends V> after);
-    public abstract OmniFunction<A, B, C, D, E, F, G, H, I, R> negate();
+    public abstract OmniFunction<A, B, C, D, E, F, G, H, I, J, K, R> negate();
 
     @Override
     public void accept(A o, B o2) {
-        invoke(o, o2, null, null, null, null, null, null, null);
+        invoke(o, o2, null, null, null, null, null, null, null, null, null);
     }
 
     @Override
     public void accept(A o) {
-        invoke(o, null, null, null, null, null, null, null, null);
+        invoke(o, null, null, null, null, null, null, null, null, null, null);
     }
 
     @Override
     public void run() {
-        invoke(null, null, null, null, null, null, null, null, null);
+        invoke(null, null, null, null, null, null, null, null, null, null, null);
     }
 
     @Override
     public R get() {
-        return invoke(null, null, null, null, null, null, null, null, null);
+        return invoke(null, null, null, null, null, null, null, null, null, null, null);
     }
 
     @Override
     public boolean test(A o, B o2) {
-        return (Boolean) invoke(o, o2, null, null, null, null, null, null, null);
+        return (Boolean) invoke(o, o2, null, null, null, null, null, null, null, null, null);
     }
 
     @Override
     public boolean test(A o) {
-        return (Boolean) invoke(o, null, null, null, null, null, null, null, null);
+        return (Boolean) invoke(o, null, null, null, null, null, null, null, null, null, null);
     }
 
     @Override
@@ -113,72 +120,92 @@
 
     @Override
     public R apply(A a, B b, C c) {
-        return invoke(a, b, c, null, null, null, null, null, null);
+        return invoke(a, b, c, null, null, null, null, null, null, null, null);
     }
 
     @Override
     public void accept(A a, B b, C c) {
-        invoke(a, b, c, null, null, null, null, null, null);
+        invoke(a, b, c, null, null, null, null, null, null, null, null);
     }
 
     @Override
     public R apply(A a, B b, C c, D d) {
-        return invoke(a, b, c, d, null, null, null, null, null);
+        return invoke(a, b, c, d, null, null, null, null, null, null, null);
     }
 
     @Override
     public R apply(A a, B b, C c, D d, E e) {
-        return invoke(a, b, c, d, e, null, null, null, null);
+        return invoke(a, b, c, d, e, null, null, null, null, null, null);
     }
 
     @Override
     public R apply(A a, B b, C c, D d, E e, F f) {
-        return invoke(a, b, c, d, e, f, null, null, null);
+        return invoke(a, b, c, d, e, f, null, null, null, null, null);
     }
 
     @Override
     public R apply(A a, B b, C c, D d, E e, F f, G g) {
-        return invoke(a, b, c, d, e, f, g, null, null);
+        return invoke(a, b, c, d, e, f, g, null, null, null, null);
     }
 
     @Override
     public R apply(A a, B b, C c, D d, E e, F f, G g, H h) {
-        return invoke(a, b, c, d, e, f, g, h, null);
+        return invoke(a, b, c, d, e, f, g, h, null, null, null);
     }
 
     @Override
     public R apply(A a, B b, C c, D d, E e, F f, G g, H h, I i) {
-        return invoke(a, b, c, d, e, f, g, h, i);
+        return invoke(a, b, c, d, e, f, g, h, i, null, null);
+    }
+
+    @Override
+    public R apply(A a, B b, C c, D d, E e, F f, G g, H h, I i, J j) {
+        return invoke(a, b, c, d, e, f, g, h, i, j, null);
+    }
+
+    @Override
+    public R apply(A a, B b, C c, D d, E e, F f, G g, H h, I i, J j, K k) {
+        return invoke(a, b, c, d, e, f, g, h, i, j, k);
     }
 
     @Override
     public void accept(A a, B b, C c, D d) {
-        invoke(a, b, c, d, null, null, null, null, null);
+        invoke(a, b, c, d, null, null, null, null, null, null, null);
     }
 
     @Override
     public void accept(A a, B b, C c, D d, E e) {
-        invoke(a, b, c, d, e, null, null, null, null);
+        invoke(a, b, c, d, e, null, null, null, null, null, null);
     }
 
     @Override
     public void accept(A a, B b, C c, D d, E e, F f) {
-        invoke(a, b, c, d, e, f, null, null, null);
+        invoke(a, b, c, d, e, f, null, null, null, null, null);
     }
 
     @Override
     public void accept(A a, B b, C c, D d, E e, F f, G g) {
-        invoke(a, b, c, d, e, f, g, null, null);
+        invoke(a, b, c, d, e, f, g, null, null, null, null);
     }
 
     @Override
     public void accept(A a, B b, C c, D d, E e, F f, G g, H h) {
-        invoke(a, b, c, d, e, f, g, h, null);
+        invoke(a, b, c, d, e, f, g, h, null, null, null);
     }
 
     @Override
     public void accept(A a, B b, C c, D d, E e, F f, G g, H h, I i) {
-        invoke(a, b, c, d, e, f, g, h, i);
+        invoke(a, b, c, d, e, f, g, h, i, null, null);
+    }
+
+    @Override
+    public void accept(A a, B b, C c, D d, E e, F f, G g, H h, I i, J j) {
+        invoke(a, b, c, d, e, f, g, h, i, j, null);
+    }
+
+    @Override
+    public void accept(A a, B b, C c, D d, E e, F f, G g, H h, I i, J j, K k) {
+        invoke(a, b, c, d, e, f, g, h, i, j, k);
     }
 
     @Override
@@ -192,5 +219,5 @@
     }
 
     @Override
-    public abstract OmniFunction<A, B, C, D, E, F, G, H, I, R> recycleOnUse();
+    public abstract OmniFunction<A, B, C, D, E, F, G, H, I, J, K, R> recycleOnUse();
 }
diff --git a/core/java/com/android/internal/util/function/pooled/PooledLambda.java b/core/java/com/android/internal/util/function/pooled/PooledLambda.java
index c00932e..b9bf933 100755
--- a/core/java/com/android/internal/util/function/pooled/PooledLambda.java
+++ b/core/java/com/android/internal/util/function/pooled/PooledLambda.java
@@ -21,6 +21,8 @@
 
 import android.os.Message;
 
+import com.android.internal.util.function.DecConsumer;
+import com.android.internal.util.function.DecFunction;
 import com.android.internal.util.function.HeptConsumer;
 import com.android.internal.util.function.HeptFunction;
 import com.android.internal.util.function.HexConsumer;
@@ -35,6 +37,8 @@
 import com.android.internal.util.function.QuintFunction;
 import com.android.internal.util.function.TriConsumer;
 import com.android.internal.util.function.TriFunction;
+import com.android.internal.util.function.UndecConsumer;
+import com.android.internal.util.function.UndecFunction;
 import com.android.internal.util.function.pooled.PooledLambdaImpl.LambdaType.ReturnType;
 
 import java.util.function.BiConsumer;
@@ -181,7 +185,7 @@
             A arg1) {
         return acquire(PooledLambdaImpl.sPool,
                 function, 1, 0, ReturnType.VOID, arg1, null, null, null, null, null, null, null,
-                null);
+                null, null, null);
     }
 
     /**
@@ -198,7 +202,7 @@
             A arg1) {
         return acquire(PooledLambdaImpl.sPool,
                 function, 1, 0, ReturnType.BOOLEAN, arg1, null, null, null, null, null, null, null,
-                null);
+                null, null, null);
     }
 
     /**
@@ -215,7 +219,7 @@
             A arg1) {
         return acquire(PooledLambdaImpl.sPool,
                 function, 1, 0, ReturnType.OBJECT, arg1, null, null, null, null, null, null, null,
-                null);
+                null, null, null);
     }
 
     /**
@@ -246,7 +250,7 @@
         synchronized (Message.sPoolSync) {
             PooledRunnable callback = acquire(PooledLambdaImpl.sMessageCallbacksPool,
                     function, 1, 0, ReturnType.VOID, arg1, null, null, null, null, null, null, null,
-                    null);
+                    null, null, null);
             return Message.obtain().setCallback(callback.recycleOnUse());
         }
     }
@@ -266,7 +270,7 @@
             A arg1, B arg2) {
         return acquire(PooledLambdaImpl.sPool,
                 function, 2, 0, ReturnType.VOID, arg1, arg2, null, null, null, null, null, null,
-                null);
+                null, null, null);
     }
 
     /**
@@ -284,7 +288,7 @@
             A arg1, B arg2) {
         return acquire(PooledLambdaImpl.sPool,
                 function, 2, 0, ReturnType.BOOLEAN, arg1, arg2, null, null, null, null, null, null,
-                null);
+                null, null, null);
     }
 
     /**
@@ -302,7 +306,7 @@
             A arg1, B arg2) {
         return acquire(PooledLambdaImpl.sPool,
                 function, 2, 0, ReturnType.OBJECT, arg1, arg2, null, null, null, null, null, null,
-                null);
+                null, null, null);
     }
 
     /**
@@ -320,7 +324,7 @@
             ArgumentPlaceholder<A> arg1, B arg2) {
         return acquire(PooledLambdaImpl.sPool,
                 function, 2, 1, ReturnType.VOID, arg1, arg2, null, null, null, null, null, null,
-                null);
+                null, null, null);
     }
 
     /**
@@ -338,7 +342,7 @@
             ArgumentPlaceholder<A> arg1, B arg2) {
         return acquire(PooledLambdaImpl.sPool,
                 function, 2, 1, ReturnType.BOOLEAN, arg1, arg2, null, null, null, null, null, null,
-                null);
+                null, null, null);
     }
 
     /**
@@ -356,7 +360,7 @@
             ArgumentPlaceholder<A> arg1, B arg2) {
         return acquire(PooledLambdaImpl.sPool,
                 function, 2, 1, ReturnType.OBJECT, arg1, arg2, null, null, null, null, null, null,
-                null);
+                null, null, null);
     }
 
     /**
@@ -374,7 +378,7 @@
             A arg1, ArgumentPlaceholder<B> arg2) {
         return acquire(PooledLambdaImpl.sPool,
                 function, 2, 1, ReturnType.VOID, arg1, arg2, null, null, null, null, null, null,
-                null);
+                null, null, null);
     }
 
     /**
@@ -392,7 +396,7 @@
             A arg1, ArgumentPlaceholder<B> arg2) {
         return acquire(PooledLambdaImpl.sPool,
                 function, 2, 1, ReturnType.BOOLEAN, arg1, arg2, null, null, null, null, null, null,
-                null);
+                null, null, null);
     }
 
     /**
@@ -410,7 +414,7 @@
             A arg1, ArgumentPlaceholder<B> arg2) {
         return acquire(PooledLambdaImpl.sPool,
                 function, 2, 1, ReturnType.OBJECT, arg1, arg2, null, null, null, null, null, null,
-                null);
+                null, null, null);
     }
 
     /**
@@ -442,7 +446,7 @@
         synchronized (Message.sPoolSync) {
             PooledRunnable callback = acquire(PooledLambdaImpl.sMessageCallbacksPool,
                     function, 2, 0, ReturnType.VOID, arg1, arg2, null, null, null, null, null, null,
-                    null);
+                    null, null, null);
             return Message.obtain().setCallback(callback.recycleOnUse());
         }
     }
@@ -463,7 +467,7 @@
             A arg1, B arg2, C arg3) {
         return acquire(PooledLambdaImpl.sPool,
                 function, 3, 0, ReturnType.VOID, arg1, arg2, arg3, null, null, null, null, null,
-                null);
+                null, null, null);
     }
 
     /**
@@ -482,7 +486,7 @@
             A arg1, B arg2, C arg3) {
         return acquire(PooledLambdaImpl.sPool,
                 function, 3, 0, ReturnType.OBJECT, arg1, arg2, arg3, null, null, null, null, null,
-                null);
+                null, null, null);
     }
 
     /**
@@ -501,7 +505,7 @@
             ArgumentPlaceholder<A> arg1, B arg2, C arg3) {
         return acquire(PooledLambdaImpl.sPool,
                 function, 3, 1, ReturnType.VOID, arg1, arg2, arg3, null, null, null, null, null,
-                null);
+                null, null, null);
     }
 
     /**
@@ -520,7 +524,7 @@
             ArgumentPlaceholder<A> arg1, B arg2, C arg3) {
         return acquire(PooledLambdaImpl.sPool,
                 function, 3, 1, ReturnType.OBJECT, arg1, arg2, arg3, null, null, null, null, null,
-                null);
+                null, null, null);
     }
 
     /**
@@ -539,7 +543,7 @@
             A arg1, ArgumentPlaceholder<B> arg2, C arg3) {
         return acquire(PooledLambdaImpl.sPool,
                 function, 3, 1, ReturnType.VOID, arg1, arg2, arg3, null, null, null, null, null,
-                null);
+                null, null, null);
     }
 
     /**
@@ -558,7 +562,7 @@
             A arg1, ArgumentPlaceholder<B> arg2, C arg3) {
         return acquire(PooledLambdaImpl.sPool,
                 function, 3, 1, ReturnType.OBJECT, arg1, arg2, arg3, null, null, null, null, null,
-                null);
+                null, null, null);
     }
 
     /**
@@ -577,7 +581,7 @@
             A arg1, B arg2, ArgumentPlaceholder<C> arg3) {
         return acquire(PooledLambdaImpl.sPool,
                 function, 3, 1, ReturnType.VOID, arg1, arg2, arg3, null, null, null, null, null,
-                null);
+                null, null, null);
     }
 
     /**
@@ -596,7 +600,7 @@
             A arg1, B arg2, ArgumentPlaceholder<C> arg3) {
         return acquire(PooledLambdaImpl.sPool,
                 function, 3, 1, ReturnType.OBJECT, arg1, arg2, arg3, null, null, null, null, null,
-                null);
+                null, null, null);
     }
 
     /**
@@ -629,7 +633,7 @@
         synchronized (Message.sPoolSync) {
             PooledRunnable callback = acquire(PooledLambdaImpl.sMessageCallbacksPool,
                     function, 3, 0, ReturnType.VOID, arg1, arg2, arg3, null, null, null, null, null,
-                    null);
+                    null, null, null);
             return Message.obtain().setCallback(callback.recycleOnUse());
         }
     }
@@ -651,7 +655,7 @@
             A arg1, B arg2, C arg3, D arg4) {
         return acquire(PooledLambdaImpl.sPool,
                 function, 4, 0, ReturnType.VOID, arg1, arg2, arg3, arg4, null, null, null, null,
-                null);
+                null, null, null);
     }
 
     /**
@@ -671,7 +675,7 @@
             A arg1, B arg2, C arg3, D arg4) {
         return acquire(PooledLambdaImpl.sPool,
                 function, 4, 0, ReturnType.OBJECT, arg1, arg2, arg3, arg4, null, null, null, null,
-                null);
+                null, null, null);
     }
 
     /**
@@ -691,7 +695,7 @@
             ArgumentPlaceholder<A> arg1, B arg2, C arg3, D arg4) {
         return acquire(PooledLambdaImpl.sPool,
                 function, 4, 1, ReturnType.VOID, arg1, arg2, arg3, arg4, null, null, null, null,
-                null);
+                null, null, null);
     }
 
     /**
@@ -711,7 +715,7 @@
             ArgumentPlaceholder<A> arg1, B arg2, C arg3, D arg4) {
         return acquire(PooledLambdaImpl.sPool,
                 function, 4, 1, ReturnType.OBJECT, arg1, arg2, arg3, arg4, null, null, null, null,
-                null);
+                null, null, null);
     }
 
     /**
@@ -731,7 +735,7 @@
             A arg1, ArgumentPlaceholder<B> arg2, C arg3, D arg4) {
         return acquire(PooledLambdaImpl.sPool,
                 function, 4, 1, ReturnType.VOID, arg1, arg2, arg3, arg4, null, null, null, null,
-                null);
+                null, null, null);
     }
 
     /**
@@ -751,7 +755,7 @@
             A arg1, ArgumentPlaceholder<B> arg2, C arg3, D arg4) {
         return acquire(PooledLambdaImpl.sPool,
                 function, 4, 1, ReturnType.OBJECT, arg1, arg2, arg3, arg4, null, null, null, null,
-                null);
+                null, null, null);
     }
 
     /**
@@ -771,7 +775,7 @@
             A arg1, B arg2, ArgumentPlaceholder<C> arg3, D arg4) {
         return acquire(PooledLambdaImpl.sPool,
                 function, 4, 1, ReturnType.VOID, arg1, arg2, arg3, arg4, null, null, null, null,
-                null);
+                null, null, null);
     }
 
     /**
@@ -791,7 +795,7 @@
             A arg1, B arg2, ArgumentPlaceholder<C> arg3, D arg4) {
         return acquire(PooledLambdaImpl.sPool,
                 function, 4, 1, ReturnType.OBJECT, arg1, arg2, arg3, arg4, null, null, null, null,
-                null);
+                null, null, null);
     }
 
     /**
@@ -811,7 +815,7 @@
             A arg1, B arg2, C arg3, ArgumentPlaceholder<D> arg4) {
         return acquire(PooledLambdaImpl.sPool,
                 function, 4, 1, ReturnType.VOID, arg1, arg2, arg3, arg4, null, null, null, null,
-                null);
+                null, null, null);
     }
 
     /**
@@ -831,7 +835,7 @@
             A arg1, B arg2, C arg3, ArgumentPlaceholder<D> arg4) {
         return acquire(PooledLambdaImpl.sPool,
                 function, 4, 1, ReturnType.OBJECT, arg1, arg2, arg3, arg4, null, null, null, null,
-                null);
+                null, null, null);
     }
 
     /**
@@ -865,7 +869,7 @@
         synchronized (Message.sPoolSync) {
             PooledRunnable callback = acquire(PooledLambdaImpl.sMessageCallbacksPool,
                     function, 4, 0, ReturnType.VOID, arg1, arg2, arg3, arg4, null, null, null, null,
-                    null);
+                    null, null, null);
             return Message.obtain().setCallback(callback.recycleOnUse());
         }
     }
@@ -888,7 +892,7 @@
             A arg1, B arg2, C arg3, D arg4, E arg5) {
         return acquire(PooledLambdaImpl.sPool,
                 function, 5, 0, ReturnType.VOID, arg1, arg2, arg3, arg4, arg5, null, null, null,
-                null);
+                null, null, null);
     }
 
     /**
@@ -909,7 +913,7 @@
                     function, A arg1, B arg2, C arg3, D arg4, E arg5) {
         return acquire(PooledLambdaImpl.sPool,
                 function, 5, 0, ReturnType.OBJECT, arg1, arg2, arg3, arg4, arg5, null, null, null,
-                null);
+                null, null, null);
     }
 
     /**
@@ -945,7 +949,7 @@
         synchronized (Message.sPoolSync) {
             PooledRunnable callback = acquire(PooledLambdaImpl.sMessageCallbacksPool,
                     function, 5, 0, ReturnType.VOID, arg1, arg2, arg3, arg4, arg5, null, null, null,
-                    null);
+                    null, null, null);
             return Message.obtain().setCallback(callback.recycleOnUse());
         }
     }
@@ -969,7 +973,7 @@
             A arg1, B arg2, C arg3, D arg4, E arg5, F arg6) {
         return acquire(PooledLambdaImpl.sPool,
                 function, 6, 0, ReturnType.VOID, arg1, arg2, arg3, arg4, arg5, arg6, null, null,
-                null);
+                null, null, null);
     }
 
     /**
@@ -991,7 +995,7 @@
                     ? extends R> function, A arg1, B arg2, C arg3, D arg4, E arg5, F arg6) {
         return acquire(PooledLambdaImpl.sPool,
                 function, 6, 0, ReturnType.OBJECT, arg1, arg2, arg3, arg4, arg5, arg6, null, null,
-                null);
+                null, null, null);
     }
 
     /**
@@ -1028,7 +1032,7 @@
         synchronized (Message.sPoolSync) {
             PooledRunnable callback = acquire(PooledLambdaImpl.sMessageCallbacksPool,
                     function, 6, 0, ReturnType.VOID, arg1, arg2, arg3, arg4, arg5, arg6, null, null,
-                    null);
+                    null, null, null);
             return Message.obtain().setCallback(callback.recycleOnUse());
         }
     }
@@ -1053,7 +1057,7 @@
                     ? super G> function, A arg1, B arg2, C arg3, D arg4, E arg5, F arg6, G arg7) {
         return acquire(PooledLambdaImpl.sPool,
                 function, 7, 0, ReturnType.VOID, arg1, arg2, arg3, arg4, arg5, arg6, arg7, null,
-                null);
+                null, null, null);
     }
 
     /**
@@ -1077,7 +1081,7 @@
             A arg1, B arg2, C arg3, D arg4, E arg5, F arg6, G arg7) {
         return acquire(PooledLambdaImpl.sPool,
                 function, 7, 0, ReturnType.OBJECT, arg1, arg2, arg3, arg4, arg5, arg6, arg7, null,
-                null);
+                null, null, null);
     }
 
     /**
@@ -1115,7 +1119,7 @@
         synchronized (Message.sPoolSync) {
             PooledRunnable callback = acquire(PooledLambdaImpl.sMessageCallbacksPool,
                     function, 7, 0, ReturnType.VOID, arg1, arg2, arg3, arg4, arg5, arg6, arg7, null,
-                    null);
+                    null, null, null);
             return Message.obtain().setCallback(callback.recycleOnUse());
         }
     }
@@ -1142,7 +1146,7 @@
             H arg8) {
         return acquire(PooledLambdaImpl.sPool,
                 function, 8, 0, ReturnType.VOID, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8,
-                null);
+                null, null, null);
     }
 
     /**
@@ -1167,7 +1171,7 @@
             A arg1, B arg2, C arg3, D arg4, E arg5, F arg6, G arg7, H arg8) {
         return acquire(PooledLambdaImpl.sPool,
                 function, 8, 0, ReturnType.OBJECT, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8,
-                null);
+                null, null, null);
     }
 
     /**
@@ -1207,7 +1211,7 @@
         synchronized (Message.sPoolSync) {
             PooledRunnable callback = acquire(PooledLambdaImpl.sMessageCallbacksPool,
                     function, 8, 0, ReturnType.VOID, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8,
-                    null);
+                    null, null, null);
             return Message.obtain().setCallback(callback.recycleOnUse());
         }
     }
@@ -1235,7 +1239,7 @@
             E arg5, F arg6, G arg7, H arg8, I arg9) {
         return acquire(PooledLambdaImpl.sPool,
                 function, 9, 0, ReturnType.VOID, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8,
-                arg9);
+                arg9, null, null);
     }
 
     /**
@@ -1261,7 +1265,7 @@
             A arg1, B arg2, C arg3, D arg4, E arg5, F arg6, G arg7, H arg8, I arg9) {
         return acquire(PooledLambdaImpl.sPool,
                 function, 9, 0, ReturnType.OBJECT, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8,
-                arg9);
+                arg9, null, null);
     }
 
     /**
@@ -1302,7 +1306,209 @@
         synchronized (Message.sPoolSync) {
             PooledRunnable callback = acquire(PooledLambdaImpl.sMessageCallbacksPool,
                     function, 9, 0, ReturnType.VOID, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8,
-                    arg9);
+                    arg9, null, null);
+            return Message.obtain().setCallback(callback.recycleOnUse());
+        }
+    }
+
+    /**
+     * {@link PooledRunnable} factory
+     *
+     * @param function non-capturing lambda(typically an unbounded method reference)
+     *                 to be invoked on call
+     * @param arg1 parameter supplied to {@code function} on call
+     * @param arg2 parameter supplied to {@code function} on call
+     * @param arg3 parameter supplied to {@code function} on call
+     * @param arg4 parameter supplied to {@code function} on call
+     * @param arg5 parameter supplied to {@code function} on call
+     * @param arg6 parameter supplied to {@code function} on call
+     * @param arg7 parameter supplied to {@code function} on call
+     * @param arg8 parameter supplied to {@code function} on call
+     * @param arg9 parameter supplied to {@code function} on call
+     * @param arg10 parameter supplied to {@code function} on call
+     * @return a {@link PooledRunnable}, equivalent to lambda:
+     *         {@code () -> function(arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10) }
+     */
+    static <A, B, C, D, E, F, G, H, I, J> PooledRunnable obtainRunnable(
+            DecConsumer<? super A, ? super B, ? super C, ? super D, ? super E, ? super F,
+                    ? super G, ? super H, ? super I, ? super J> function, A arg1, B arg2, C arg3,
+            D arg4, E arg5, F arg6, G arg7, H arg8, I arg9, J arg10) {
+        return acquire(PooledLambdaImpl.sPool,
+                function, 10, 0, ReturnType.VOID, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8,
+                arg9, arg10, null);
+    }
+
+    /**
+     * {@link PooledSupplier} factory
+     *
+     * @param function non-capturing lambda(typically an unbounded method reference)
+     *                 to be invoked on call
+     * @param arg1 parameter supplied to {@code function} on call
+     * @param arg2 parameter supplied to {@code function} on call
+     * @param arg3 parameter supplied to {@code function} on call
+     * @param arg4 parameter supplied to {@code function} on call
+     * @param arg5 parameter supplied to {@code function} on call
+     * @param arg6 parameter supplied to {@code function} on call
+     * @param arg7 parameter supplied to {@code function} on call
+     * @param arg8 parameter supplied to {@code function} on call
+     * @param arg9 parameter supplied to {@code function} on call
+     * @param arg10 parameter supplied to {@code function} on call
+     * @return a {@link PooledSupplier}, equivalent to lambda:
+     *         {@code () -> function(arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10) }
+     */
+    static <A, B, C, D, E, F, G, H, I, J, R> PooledSupplier<R> obtainSupplier(
+            DecFunction<? super A, ? super B, ? super C, ? super D, ? super E, ? super F,
+                                ? super G, ? super H, ? super I, ? super J, ? extends R> function,
+            A arg1, B arg2, C arg3, D arg4, E arg5, F arg6, G arg7, H arg8, I arg9, J arg10) {
+        return acquire(PooledLambdaImpl.sPool,
+                function, 10, 0, ReturnType.OBJECT, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8,
+                arg9, arg10, null);
+    }
+
+    /**
+     * Factory of {@link Message}s that contain an
+     * ({@link PooledLambda#recycleOnUse auto-recycling}) {@link PooledRunnable} as its
+     * {@link Message#getCallback internal callback}.
+     *
+     * The callback is equivalent to one obtainable via
+     * {@link #obtainRunnable(QuintConsumer, Object, Object, Object, Object, Object)}
+     *
+     * Note that using this method with {@link android.os.Handler#handleMessage}
+     * is more efficient than the alternative of {@link android.os.Handler#post}
+     * with a {@link PooledRunnable} due to the lack of 2 separate synchronization points
+     * when obtaining {@link Message} and {@link PooledRunnable} from pools separately
+     *
+     * You may optionally set a {@link Message#what} for the message if you want to be
+     * able to cancel it via {@link android.os.Handler#removeMessages}, but otherwise
+     * there's no need to do so
+     *
+     * @param function non-capturing lambda(typically an unbounded method reference)
+     *                 to be invoked on call
+     * @param arg1 parameter supplied to {@code function} on call
+     * @param arg2 parameter supplied to {@code function} on call
+     * @param arg3 parameter supplied to {@code function} on call
+     * @param arg4 parameter supplied to {@code function} on call
+     * @param arg5 parameter supplied to {@code function} on call
+     * @param arg6 parameter supplied to {@code function} on call
+     * @param arg7 parameter supplied to {@code function} on call
+     * @param arg8 parameter supplied to {@code function} on call
+     * @param arg9 parameter supplied to {@code function} on call
+     * @param arg10 parameter supplied to {@code function} on call
+     * @return a {@link Message} invoking {@code function(arg1, arg2, arg3, arg4, arg5, arg6,
+     * arg7, arg8, arg9, arg10) } when handled
+     */
+    static <A, B, C, D, E, F, G, H, I, J> Message obtainMessage(
+            DecConsumer<? super A, ? super B, ? super C, ? super D, ? super E, ? super F,
+                    ? super G, ? super H, ? super I, ? super J> function, A arg1, B arg2, C arg3,
+            D arg4, E arg5, F arg6, G arg7, H arg8, I arg9, J arg10) {
+        synchronized (Message.sPoolSync) {
+            PooledRunnable callback = acquire(PooledLambdaImpl.sMessageCallbacksPool,
+                    function, 10, 0, ReturnType.VOID, arg1, arg2, arg3, arg4, arg5, arg6, arg7,
+                    arg8, arg9, arg10, null);
+            return Message.obtain().setCallback(callback.recycleOnUse());
+        }
+    }
+
+    /**
+     * {@link PooledRunnable} factory
+     *
+     * @param function non-capturing lambda(typically an unbounded method reference)
+     *                 to be invoked on call
+     * @param arg1 parameter supplied to {@code function} on call
+     * @param arg2 parameter supplied to {@code function} on call
+     * @param arg3 parameter supplied to {@code function} on call
+     * @param arg4 parameter supplied to {@code function} on call
+     * @param arg5 parameter supplied to {@code function} on call
+     * @param arg6 parameter supplied to {@code function} on call
+     * @param arg7 parameter supplied to {@code function} on call
+     * @param arg8 parameter supplied to {@code function} on call
+     * @param arg9 parameter supplied to {@code function} on call
+     * @param arg10 parameter supplied to {@code function} on call
+     * @param arg11 parameter supplied to {@code function} on call
+     * @return a {@link PooledRunnable}, equivalent to lambda:
+     *         {@code () -> function(arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10,
+     *         arg11) }
+     */
+    static <A, B, C, D, E, F, G, H, I, J, K> PooledRunnable obtainRunnable(
+            UndecConsumer<? super A, ? super B, ? super C, ? super D, ? super E, ? super F,
+                    ? super G, ? super H, ? super I, ? super J, ? super K> function, A arg1, B arg2,
+            C arg3, D arg4, E arg5, F arg6, G arg7, H arg8, I arg9, J arg10, K arg11) {
+        return acquire(PooledLambdaImpl.sPool,
+                function, 11, 0, ReturnType.VOID, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8,
+                arg9, arg10, arg11);
+    }
+
+    /**
+     * {@link PooledSupplier} factory
+     *
+     * @param function non-capturing lambda(typically an unbounded method reference)
+     *                 to be invoked on call
+     * @param arg1 parameter supplied to {@code function} on call
+     * @param arg2 parameter supplied to {@code function} on call
+     * @param arg3 parameter supplied to {@code function} on call
+     * @param arg4 parameter supplied to {@code function} on call
+     * @param arg5 parameter supplied to {@code function} on call
+     * @param arg6 parameter supplied to {@code function} on call
+     * @param arg7 parameter supplied to {@code function} on call
+     * @param arg8 parameter supplied to {@code function} on call
+     * @param arg9 parameter supplied to {@code function} on call
+     * @param arg10 parameter supplied to {@code function} on call
+     * @param arg11 parameter supplied to {@code function} on call
+     * @return a {@link PooledSupplier}, equivalent to lambda:
+     *         {@code () -> function(arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10,
+     *         arg11) }
+     */
+    static <A, B, C, D, E, F, G, H, I, J, K, R> PooledSupplier<R> obtainSupplier(
+            UndecFunction<? super A, ? super B, ? super C, ? super D, ? super E, ? super F,
+                    ? super G, ? super H, ? super I, ? super J, ? super K, ? extends R> function,
+            A arg1, B arg2, C arg3, D arg4, E arg5, F arg6, G arg7, H arg8, I arg9, J arg10,
+            K arg11) {
+        return acquire(PooledLambdaImpl.sPool,
+                function, 11, 0, ReturnType.OBJECT, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8,
+                arg9, arg10, arg11);
+    }
+
+    /**
+     * Factory of {@link Message}s that contain an
+     * ({@link PooledLambda#recycleOnUse auto-recycling}) {@link PooledRunnable} as its
+     * {@link Message#getCallback internal callback}.
+     *
+     * The callback is equivalent to one obtainable via
+     * {@link #obtainRunnable(QuintConsumer, Object, Object, Object, Object, Object)}
+     *
+     * Note that using this method with {@link android.os.Handler#handleMessage}
+     * is more efficient than the alternative of {@link android.os.Handler#post}
+     * with a {@link PooledRunnable} due to the lack of 2 separate synchronization points
+     * when obtaining {@link Message} and {@link PooledRunnable} from pools separately
+     *
+     * You may optionally set a {@link Message#what} for the message if you want to be
+     * able to cancel it via {@link android.os.Handler#removeMessages}, but otherwise
+     * there's no need to do so
+     *
+     * @param function non-capturing lambda(typically an unbounded method reference)
+     *                 to be invoked on call
+     * @param arg1 parameter supplied to {@code function} on call
+     * @param arg2 parameter supplied to {@code function} on call
+     * @param arg3 parameter supplied to {@code function} on call
+     * @param arg4 parameter supplied to {@code function} on call
+     * @param arg5 parameter supplied to {@code function} on call
+     * @param arg6 parameter supplied to {@code function} on call
+     * @param arg7 parameter supplied to {@code function} on call
+     * @param arg8 parameter supplied to {@code function} on call
+     * @param arg9 parameter supplied to {@code function} on call
+     * @param arg10 parameter supplied to {@code function} on call
+     * @param arg11 parameter supplied to {@code function} on call
+     * @return a {@link Message} invoking {@code function(arg1, arg2, arg3, arg4, arg5, arg6,
+     * arg7, arg8, arg9, arg10, arg11) } when handled
+     */
+    static <A, B, C, D, E, F, G, H, I, J, K> Message obtainMessage(
+            UndecConsumer<? super A, ? super B, ? super C, ? super D, ? super E, ? super F,
+                    ? super G, ? super H, ? super I, ? super J, ? super K> function, A arg1, B arg2,
+            C arg3, D arg4, E arg5, F arg6, G arg7, H arg8, I arg9, J arg10, K arg11) {
+        synchronized (Message.sPoolSync) {
+            PooledRunnable callback = acquire(PooledLambdaImpl.sMessageCallbacksPool,
+                    function, 11, 0, ReturnType.VOID, arg1, arg2, arg3, arg4, arg5, arg6, arg7,
+                    arg8, arg9, arg10, arg11);
             return Message.obtain().setCallback(callback.recycleOnUse());
         }
     }
diff --git a/core/java/com/android/internal/util/function/pooled/PooledLambdaImpl.java b/core/java/com/android/internal/util/function/pooled/PooledLambdaImpl.java
index e12c031..c7502ef 100755
--- a/core/java/com/android/internal/util/function/pooled/PooledLambdaImpl.java
+++ b/core/java/com/android/internal/util/function/pooled/PooledLambdaImpl.java
@@ -26,6 +26,9 @@
 import com.android.internal.util.ArrayUtils;
 import com.android.internal.util.BitUtils;
 import com.android.internal.util.Preconditions;
+import com.android.internal.util.function.DecConsumer;
+import com.android.internal.util.function.DecFunction;
+import com.android.internal.util.function.DecPredicate;
 import com.android.internal.util.function.HeptConsumer;
 import com.android.internal.util.function.HeptFunction;
 import com.android.internal.util.function.HeptPredicate;
@@ -47,6 +50,9 @@
 import com.android.internal.util.function.TriConsumer;
 import com.android.internal.util.function.TriFunction;
 import com.android.internal.util.function.TriPredicate;
+import com.android.internal.util.function.UndecConsumer;
+import com.android.internal.util.function.UndecFunction;
+import com.android.internal.util.function.UndecPredicate;
 
 import java.util.Arrays;
 import java.util.Objects;
@@ -63,12 +69,12 @@
  * @hide
  */
 final class PooledLambdaImpl<R> extends OmniFunction<Object,
-        Object, Object, Object, Object, Object, Object, Object, Object, R> {
+        Object, Object, Object, Object, Object, Object, Object, Object, Object, Object, R> {
 
     private static final boolean DEBUG = false;
     private static final String LOG_TAG = "PooledLambdaImpl";
 
-    private static final int MAX_ARGS = 9;
+    private static final int MAX_ARGS = 11;
 
     private static final int MAX_POOL_SIZE = 50;
 
@@ -134,7 +140,7 @@
 
     /**
      * Bit schema:
-     * AAAAAAAAABCDEEEEEEFFFFFF
+     * AAAAAAAAAAABCDEEEEEEFFFFFF
      *
      * Where:
      * A - whether {@link #mArgs arg} at corresponding index was specified at
@@ -171,18 +177,18 @@
 
     @Override
     R invoke(Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, Object a7,
-            Object a8, Object a9) {
+            Object a8, Object a9, Object a10, Object a11) {
         checkNotRecycled();
         if (DEBUG) {
             Log.i(LOG_TAG, this + ".invoke("
                     + commaSeparateFirstN(
-                            new Object[] { a1, a2, a3, a4, a5, a6, a7, a8, a9 },
+                            new Object[] { a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11 },
                             LambdaType.decodeArgCount(getFlags(MASK_EXPOSED_AS)))
                     + ")");
         }
         final boolean notUsed = fillInArg(a1) && fillInArg(a2) && fillInArg(a3) && fillInArg(a4)
                 && fillInArg(a5) && fillInArg(a6) && fillInArg(a7) && fillInArg(a8)
-                && fillInArg(a9);
+                && fillInArg(a9) && fillInArg(a10) && fillInArg(a11);
         int argCount = LambdaType.decodeArgCount(getFlags(MASK_FUNC_TYPE));
         if (argCount != LambdaType.MASK_ARG_COUNT) {
             for (int i = 0; i < argCount; i++) {
@@ -410,6 +416,48 @@
                     }
                 }
             } break;
+
+            case 10: {
+                switch (returnType) {
+                    case LambdaType.ReturnType.VOID: {
+                        ((DecConsumer) mFunc).accept(popArg(0), popArg(1),
+                                popArg(2), popArg(3), popArg(4), popArg(5),
+                                popArg(6), popArg(7), popArg(8), popArg(9));
+                        return null;
+                    }
+                    case LambdaType.ReturnType.BOOLEAN: {
+                        return (R) (Object) ((DecPredicate) mFunc).test(popArg(0),
+                                popArg(1), popArg(2), popArg(3), popArg(4),
+                                popArg(5), popArg(6), popArg(7), popArg(8), popArg(9));
+                    }
+                    case LambdaType.ReturnType.OBJECT: {
+                        return (R) ((DecFunction) mFunc).apply(popArg(0), popArg(1),
+                                popArg(2), popArg(3), popArg(4), popArg(5),
+                                popArg(6), popArg(7), popArg(8), popArg(9));
+                    }
+                }
+            } break;
+
+            case 11: {
+                switch (returnType) {
+                    case LambdaType.ReturnType.VOID: {
+                        ((UndecConsumer) mFunc).accept(popArg(0), popArg(1),
+                                popArg(2), popArg(3), popArg(4), popArg(5),
+                                popArg(6), popArg(7), popArg(8), popArg(9), popArg(10));
+                        return null;
+                    }
+                    case LambdaType.ReturnType.BOOLEAN: {
+                        return (R) (Object) ((UndecPredicate) mFunc).test(popArg(0),
+                                popArg(1), popArg(2), popArg(3), popArg(4),
+                                popArg(5), popArg(6), popArg(7), popArg(8), popArg(9), popArg(10));
+                    }
+                    case LambdaType.ReturnType.OBJECT: {
+                        return (R) ((UndecFunction) mFunc).apply(popArg(0), popArg(1),
+                                popArg(2), popArg(3), popArg(4), popArg(5),
+                                popArg(6), popArg(7), popArg(8), popArg(9), popArg(10));
+                    }
+                }
+            } break;
         }
         throw new IllegalStateException("Unknown function type: " + LambdaType.toString(funcType));
     }
@@ -475,7 +523,7 @@
      */
     static <E extends PooledLambda> E acquire(Pool pool, Object func,
             int fNumArgs, int numPlaceholders, int fReturnType, Object a, Object b, Object c,
-            Object d, Object e, Object f, Object g, Object h, Object i) {
+            Object d, Object e, Object f, Object g, Object h, Object i, Object j, Object k) {
         PooledLambdaImpl r = acquire(pool);
         if (DEBUG) {
             Log.i(LOG_TAG,
@@ -493,6 +541,8 @@
                             + ", g = " + g
                             + ", h = " + h
                             + ", i = " + i
+                            + ", j = " + j
+                            + ", k = " + k
                             + ")");
         }
         r.mFunc = Preconditions.checkNotNull(func);
@@ -508,6 +558,8 @@
         setIfInBounds(r.mArgs, 6, g);
         setIfInBounds(r.mArgs, 7, h);
         setIfInBounds(r.mArgs, 8, i);
+        setIfInBounds(r.mArgs, 9, j);
+        setIfInBounds(r.mArgs, 10, k);
         return (E) r;
     }
 
@@ -564,13 +616,13 @@
 
     @Override
     public OmniFunction<Object, Object, Object, Object, Object, Object, Object, Object, Object,
-            R> negate() {
+            Object, Object, R> negate() {
         throw new UnsupportedOperationException();
     }
 
     @Override
     public <V> OmniFunction<Object, Object, Object, Object, Object, Object, Object, Object, Object,
-            V> andThen(Function<? super R, ? extends V> after) {
+            Object, Object, V> andThen(Function<? super R, ? extends V> after) {
         throw new UnsupportedOperationException();
     }
 
@@ -591,7 +643,7 @@
 
     @Override
     public OmniFunction<Object, Object, Object, Object, Object, Object, Object, Object, Object,
-            R> recycleOnUse() {
+            Object, Object, R> recycleOnUse() {
         if (DEBUG) Log.i(LOG_TAG, this + ".recycleOnUse()");
         mFlags |= FLAG_RECYCLE_ON_USE;
         return this;
@@ -683,6 +735,8 @@
                 case 7: return "Hept";
                 case 8: return "Oct";
                 case 9: return "Nona";
+                case 10: return "Dec";
+                case 11: return "Undec";
                 default: return "" + argCount + "arg";
             }
         }
diff --git a/core/java/com/android/internal/view/BaseIWindow.java b/core/java/com/android/internal/view/BaseIWindow.java
index cc468f4..0e078dd 100644
--- a/core/java/com/android/internal/view/BaseIWindow.java
+++ b/core/java/com/android/internal/view/BaseIWindow.java
@@ -30,6 +30,7 @@
 import android.view.InsetsSourceControl;
 import android.view.InsetsState;
 import android.view.PointerIcon;
+import android.view.WindowInsets.Type.InsetType;
 
 import com.android.internal.os.IResultReceiver;
 
@@ -75,6 +76,10 @@
     }
 
     @Override
+    public void showInsets(@InsetType int types, boolean fromIme)  throws RemoteException {
+    }
+
+    @Override
     public void moved(int newX, int newY) {
     }
 
diff --git a/core/jni/Android.bp b/core/jni/Android.bp
index 0505fe3..ce405fe 100644
--- a/core/jni/Android.bp
+++ b/core/jni/Android.bp
@@ -117,6 +117,7 @@
                 "android_view_RenderNodeAnimator.cpp",
                 "android_view_Surface.cpp",
                 "android_view_SurfaceControl.cpp",
+                "android_graphics_BLASTBufferQueue.cpp",
                 "android_view_SurfaceSession.cpp",
                 "android_view_TextureView.cpp",
                 "android_view_VelocityTracker.cpp",
@@ -257,8 +258,6 @@
                 "libnativeloader_lazy",
                 "libmemunreachable",
                 "libhidlbase",
-                "libhidltransport",
-                "libhwbinder",
                 "libvintf",
                 "libnativewindow",
                 "libdl",
diff --git a/core/jni/AndroidRuntime.cpp b/core/jni/AndroidRuntime.cpp
index d476d2d..3497f92 100644
--- a/core/jni/AndroidRuntime.cpp
+++ b/core/jni/AndroidRuntime.cpp
@@ -115,6 +115,7 @@
 extern int register_android_content_StringBlock(JNIEnv* env);
 extern int register_android_content_XmlBlock(JNIEnv* env);
 extern int register_android_content_res_ApkAssets(JNIEnv* env);
+extern int register_android_graphics_BLASTBufferQueue(JNIEnv* env);
 extern int register_android_view_DisplayEventReceiver(JNIEnv* env);
 extern int register_android_view_InputApplicationHandle(JNIEnv* env);
 extern int register_android_view_InputWindowHandle(JNIEnv* env);
@@ -1458,10 +1459,9 @@
     REG_JNI(register_android_opengl_jni_GLES31),
     REG_JNI(register_android_opengl_jni_GLES31Ext),
     REG_JNI(register_android_opengl_jni_GLES32),
-
     REG_JNI(register_android_graphics_classes),
+    REG_JNI(register_android_graphics_BLASTBufferQueue),
     REG_JNI(register_android_graphics_GraphicBuffer),
-
     REG_JNI(register_android_database_CursorWindow),
     REG_JNI(register_android_database_SQLiteConnection),
     REG_JNI(register_android_database_SQLiteGlobal),
diff --git a/core/jni/android_graphics_BLASTBufferQueue.cpp b/core/jni/android_graphics_BLASTBufferQueue.cpp
new file mode 100644
index 0000000..185e581
--- /dev/null
+++ b/core/jni/android_graphics_BLASTBufferQueue.cpp
@@ -0,0 +1,82 @@
+/*
+ * 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.
+ */
+
+#define LOG_TAG "BLASTBufferQueue"
+
+#include <nativehelper/JNIHelp.h>
+
+#include <android_runtime/AndroidRuntime.h>
+#include <android_runtime/android_view_Surface.h>
+#include <utils/Log.h>
+#include <utils/RefBase.h>
+
+#include <gui/BLASTBufferQueue.h>
+#include <gui/Surface.h>
+#include <gui/SurfaceComposerClient.h>
+
+namespace android {
+
+static jlong nativeCreate(JNIEnv* env, jclass clazz, jlong surfaceControl, jlong width, jlong height) {
+    sp<BLASTBufferQueue> queue = new BLASTBufferQueue(
+            reinterpret_cast<SurfaceControl*>(surfaceControl), width, height);
+    queue->incStrong((void*)nativeCreate);
+    return reinterpret_cast<jlong>(queue.get());
+}
+
+static void nativeDestroy(JNIEnv* env, jclass clazz, jlong ptr) {
+    sp<BLASTBufferQueue> queue = reinterpret_cast<BLASTBufferQueue*>(ptr);
+    queue->decStrong((void*)nativeCreate);
+}
+
+static jobject nativeGetSurface(JNIEnv* env, jclass clazz, jlong ptr) {
+    sp<BLASTBufferQueue> queue = reinterpret_cast<BLASTBufferQueue*>(ptr);
+    return android_view_Surface_createFromIGraphicBufferProducer(env, queue->getIGraphicBufferProducer());
+}
+
+static void nativeSetNextTransaction(JNIEnv* env, jclass clazz, jlong ptr, jlong transactionPtr) {
+    sp<BLASTBufferQueue> queue = reinterpret_cast<BLASTBufferQueue*>(ptr);
+    auto transaction = reinterpret_cast<SurfaceComposerClient::Transaction*>(transactionPtr);
+    queue->setNextTransaction(transaction);
+}
+
+static void nativeUpdate(JNIEnv*env, jclass clazz, jlong ptr, jlong surfaceControl, jlong width, jlong height) {
+    sp<BLASTBufferQueue> queue = reinterpret_cast<BLASTBufferQueue*>(ptr);
+    queue->update(reinterpret_cast<SurfaceControl*>(surfaceControl), width, height);
+}
+
+static const JNINativeMethod gMethods[] = {
+    /* name, signature, funcPtr */
+    { "nativeCreate", "(JJJ)J",
+            (void*)nativeCreate },
+    {  "nativeGetSurface", "(J)Landroid/view/Surface;",
+       (void*)nativeGetSurface },
+    { "nativeDestroy", "(J)V",
+            (void*)nativeDestroy },
+    { "nativeSetNextTransaction", "(JJ)V",
+      (void*)nativeSetNextTransaction },
+    { "nativeUpdate", "(JJJJ)V",
+      (void*)nativeUpdate }
+};
+
+int register_android_graphics_BLASTBufferQueue(JNIEnv* env) {
+    int res = jniRegisterNativeMethods(env, "android/graphics/BLASTBufferQueue",
+            gMethods, NELEM(gMethods));
+    LOG_ALWAYS_FATAL_IF(res < 0, "Unable to register native methods.");
+
+    return 0;
+}
+
+} // namespace android
diff --git a/core/jni/android_os_Debug.cpp b/core/jni/android_os_Debug.cpp
index f2a4f4f..9445319 100644
--- a/core/jni/android_os_Debug.cpp
+++ b/core/jni/android_os_Debug.cpp
@@ -85,7 +85,8 @@
     // Dalvik other extra sections.
     HEAP_DALVIK_OTHER_LINEARALLOC,
     HEAP_DALVIK_OTHER_ACCOUNTING,
-    HEAP_DALVIK_OTHER_CODE_CACHE,
+    HEAP_DALVIK_OTHER_ZYGOTE_CODE_CACHE,
+    HEAP_DALVIK_OTHER_APP_CODE_CACHE,
     HEAP_DALVIK_OTHER_COMPILER_METADATA,
     HEAP_DALVIK_OTHER_INDIRECT_REFERENCE_TABLE,
 
@@ -282,9 +283,10 @@
             is_swappable = true;
         } else if (base::EndsWith(name, ".vdex")) {
             which_heap = HEAP_DEX;
-            // Handle system@framework@boot and system/framework/boot
+            // Handle system@framework@boot and system/framework/boot|apex
             if ((strstr(name.c_str(), "@boot") != nullptr) ||
-                    (strstr(name.c_str(), "/boot"))) {
+                    (strstr(name.c_str(), "/boot") != nullptr) ||
+                    (strstr(name.c_str(), "/apex") != nullptr)) {
                 sub_heap = HEAP_DEX_BOOT_VDEX;
             } else {
                 sub_heap = HEAP_DEX_APP_VDEX;
@@ -295,9 +297,10 @@
             is_swappable = true;
         } else if (base::EndsWith(name, ".art") || base::EndsWith(name, ".art]")) {
             which_heap = HEAP_ART;
-            // Handle system@framework@boot* and system/framework/boot*
+            // Handle system@framework@boot* and system/framework/boot|apex*
             if ((strstr(name.c_str(), "@boot") != nullptr) ||
-                    (strstr(name.c_str(), "/boot"))) {
+                    (strstr(name.c_str(), "/boot") != nullptr) ||
+                    (strstr(name.c_str(), "/apex") != nullptr)) {
                 sub_heap = HEAP_ART_BOOT;
             } else {
                 sub_heap = HEAP_ART_APP;
@@ -309,9 +312,18 @@
                 which_heap = HEAP_GL_DEV;
             } else if (base::StartsWith(name, "/dev/ashmem/CursorWindow")) {
                 which_heap = HEAP_CURSOR;
+            } else if (base::StartsWith(name, "/dev/ashmem/jit-zygote-cache")) {
+                which_heap = HEAP_DALVIK_OTHER;
+                sub_heap = HEAP_DALVIK_OTHER_ZYGOTE_CODE_CACHE;
             } else if (base::StartsWith(name, "/dev/ashmem")) {
                 which_heap = HEAP_ASHMEM;
             }
+        } else if (base::StartsWith(name, "/memfd:jit-cache")) {
+          which_heap = HEAP_DALVIK_OTHER;
+          sub_heap = HEAP_DALVIK_OTHER_APP_CODE_CACHE;
+        } else if (base::StartsWith(name, "/memfd:jit-zygote-cache")) {
+          which_heap = HEAP_DALVIK_OTHER;
+          sub_heap = HEAP_DALVIK_OTHER_ZYGOTE_CODE_CACHE;
         } else if (base::StartsWith(name, "[anon:")) {
             which_heap = HEAP_UNKNOWN;
             if (base::StartsWith(name, "[anon:dalvik-")) {
@@ -339,7 +351,7 @@
                     sub_heap = HEAP_DALVIK_OTHER_INDIRECT_REFERENCE_TABLE;
                 } else if (base::StartsWith(name, "[anon:dalvik-jit-code-cache") ||
                         base::StartsWith(name, "[anon:dalvik-data-code-cache")) {
-                    sub_heap = HEAP_DALVIK_OTHER_CODE_CACHE;
+                    sub_heap = HEAP_DALVIK_OTHER_APP_CODE_CACHE;
                 } else if (base::StartsWith(name, "[anon:dalvik-CompilerMetadata")) {
                     sub_heap = HEAP_DALVIK_OTHER_COMPILER_METADATA;
                 } else {
diff --git a/core/jni/android_os_GraphicsEnvironment.cpp b/core/jni/android_os_GraphicsEnvironment.cpp
index be9aee4..7582cae 100644
--- a/core/jni/android_os_GraphicsEnvironment.cpp
+++ b/core/jni/android_os_GraphicsEnvironment.cpp
@@ -85,6 +85,10 @@
     }
 }
 
+bool setInjectLayersPrSetDumpable_native() {
+    return android::GraphicsEnv::getInstance().setInjectLayersPrSetDumpable();
+}
+
 void hintActivityLaunch_native(JNIEnv* env, jobject clazz) {
     android::GraphicsEnv::getInstance().hintActivityLaunch();
 }
@@ -93,6 +97,7 @@
     { "getCanLoadSystemLibraries", "()I", reinterpret_cast<void*>(getCanLoadSystemLibraries_native) },
     { "setDriverPathAndSphalLibraries", "(Ljava/lang/String;Ljava/lang/String;)V", reinterpret_cast<void*>(setDriverPathAndSphalLibraries_native) },
     { "setGpuStats", "(Ljava/lang/String;Ljava/lang/String;JJLjava/lang/String;I)V", reinterpret_cast<void*>(setGpuStats_native) },
+    { "setInjectLayersPrSetDumpable", "()Z", reinterpret_cast<void*>(setInjectLayersPrSetDumpable_native) },
     { "setAngleInfo", "(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/io/FileDescriptor;JJ)V", reinterpret_cast<void*>(setAngleInfo_native) },
     { "getShouldUseAngle", "(Ljava/lang/String;)Z", reinterpret_cast<void*>(shouldUseAngle_native) },
     { "setLayerPaths", "(Ljava/lang/ClassLoader;Ljava/lang/String;)V", reinterpret_cast<void*>(setLayerPaths_native) },
diff --git a/core/jni/android_os_Parcel.cpp b/core/jni/android_os_Parcel.cpp
index d80c071..483b455 100644
--- a/core/jni/android_os_Parcel.cpp
+++ b/core/jni/android_os_Parcel.cpp
@@ -721,8 +721,11 @@
     {"nativeWriteFloat",          "(JF)V", (void*)android_os_Parcel_writeFloat},
     // @FastNative
     {"nativeWriteDouble",         "(JD)V", (void*)android_os_Parcel_writeDouble},
+    // @FastNative
     {"nativeWriteString",         "(JLjava/lang/String;)V", (void*)android_os_Parcel_writeString},
+    // @FastNative
     {"nativeWriteStrongBinder",   "(JLandroid/os/IBinder;)V", (void*)android_os_Parcel_writeStrongBinder},
+    // @FastNative
     {"nativeWriteFileDescriptor", "(JLjava/io/FileDescriptor;)J", (void*)android_os_Parcel_writeFileDescriptor},
 
     {"nativeCreateByteArray",     "(J)[B", (void*)android_os_Parcel_createByteArray},
@@ -736,8 +739,11 @@
     {"nativeReadFloat",           "(J)F", (void*)android_os_Parcel_readFloat},
     // @CriticalNative
     {"nativeReadDouble",          "(J)D", (void*)android_os_Parcel_readDouble},
+    // @FastNative
     {"nativeReadString",          "(J)Ljava/lang/String;", (void*)android_os_Parcel_readString},
+    // @FastNative
     {"nativeReadStrongBinder",    "(J)Landroid/os/IBinder;", (void*)android_os_Parcel_readStrongBinder},
+    // @FastNative
     {"nativeReadFileDescriptor",  "(J)Ljava/io/FileDescriptor;", (void*)android_os_Parcel_readFileDescriptor},
 
     {"nativeCreate",              "()J", (void*)android_os_Parcel_create},
diff --git a/core/jni/android_util_Binder.cpp b/core/jni/android_util_Binder.cpp
index 0afbaa0e..e406e22 100644
--- a/core/jni/android_util_Binder.cpp
+++ b/core/jni/android_util_Binder.cpp
@@ -697,6 +697,9 @@
 // same IBinder, and the original BinderProxy is still alive, return the same BinderProxy.
 jobject javaObjectForIBinder(JNIEnv* env, const sp<IBinder>& val)
 {
+    // N.B. This function is called from a @FastNative JNI method, so don't take locks around
+    // calls to Java code or block the calling thread for a long time for any reason.
+
     if (val == NULL) return NULL;
 
     if (val->checkSubclass(&gBinderOffsets)) {
diff --git a/core/jni/android_util_Process.cpp b/core/jni/android_util_Process.cpp
index 8aa6f86..0fada1b 100644
--- a/core/jni/android_util_Process.cpp
+++ b/core/jni/android_util_Process.cpp
@@ -35,6 +35,7 @@
 #include <limits>
 #include <memory>
 #include <string>
+#include <unordered_map>
 #include <vector>
 
 #include "core_jni_helpers.h"
@@ -81,6 +82,25 @@
 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) {
@@ -191,11 +211,24 @@
     return -1;
 }
 
+static bool verifyGroup(JNIEnv* env, int grp)
+{
+    if (grp < SP_DEFAULT || grp  >= SP_CNT) {
+        signalExceptionForError(env, EINVAL, grp);
+        return false;
+    }
+    return true;
+}
+
 void android_os_Process_setThreadGroup(JNIEnv* env, jobject clazz, int tid, jint grp)
 {
     ALOGV("%s tid=%d grp=%" PRId32, __func__, tid, grp);
-    SchedPolicy sp = (SchedPolicy) grp;
-    int res = set_sched_policy(tid, sp);
+    if (!verifyGroup(env, grp)) {
+        return;
+    }
+
+    int res = SetTaskProfiles(tid, {kSchedProfileMap.at(grp)}, true) ? 0 : -1;
+
     if (res != NO_ERROR) {
         signalExceptionForGroupError(env, -res, tid);
     }
@@ -204,14 +237,12 @@
 void android_os_Process_setThreadGroupAndCpuset(JNIEnv* env, jobject clazz, int tid, jint grp)
 {
     ALOGV("%s tid=%d grp=%" PRId32, __func__, tid, grp);
-    SchedPolicy sp = (SchedPolicy) grp;
-    int res = set_sched_policy(tid, sp);
-
-    if (res != NO_ERROR) {
-        signalExceptionForGroupError(env, -res, tid);
+    if (!verifyGroup(env, grp)) {
+        return;
     }
 
-    res = set_cpuset_policy(tid, sp);
+    int res = SetTaskProfiles(tid, {kCpusetProfileMap.at(grp)}, true) ? 0 : -1;
+
     if (res != NO_ERROR) {
         signalExceptionForGroupError(env, -res, tid);
     }
@@ -224,7 +255,11 @@
     char proc_path[255];
     struct dirent *de;
 
-    if ((grp == SP_FOREGROUND) || (grp > SP_MAX)) {
+    if (!verifyGroup(env, grp)) {
+        return;
+    }
+
+    if (grp == SP_FOREGROUND) {
         signalExceptionForGroupError(env, EINVAL, pid);
         return;
     }
@@ -234,7 +269,6 @@
         grp = SP_FOREGROUND;
         isDefault = true;
     }
-    SchedPolicy sp = (SchedPolicy) grp;
 
     if (kDebugPolicy) {
         char cmdline[32];
@@ -250,7 +284,7 @@
             close(fd);
         }
 
-        if (sp == SP_BACKGROUND) {
+        if (grp == SP_BACKGROUND) {
             ALOGD("setProcessGroup: vvv pid %d (%s)", pid, cmdline);
         } else {
             ALOGD("setProcessGroup: ^^^ pid %d (%s)", pid, cmdline);
@@ -268,6 +302,7 @@
     while ((de = readdir(d))) {
         int t_pid;
         int t_pri;
+        int err;
 
         if (de->d_name[0] == '.')
             continue;
@@ -293,28 +328,16 @@
             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)
-                if (cpusets_enabled()) {
-                    int err = set_cpuset_policy(t_pid, sp);
-                    if (err != NO_ERROR) {
-                        signalExceptionForGroupError(env, -err, t_pid);
-                        break;
-                    }
+                err = SetTaskProfiles(t_pid, {kCpusetProfileMap.at(grp)}, true) ? 0 : -1;
+                if (err != NO_ERROR) {
+                    signalExceptionForGroupError(env, -err, t_pid);
+                    break;
                 }
                 continue;
             }
         }
-        int err;
 
-        if (cpusets_enabled()) {
-            // set both cpuset and cgroup for general threads
-            err = set_cpuset_policy(t_pid, sp);
-            if (err != NO_ERROR) {
-                signalExceptionForGroupError(env, -err, t_pid);
-                break;
-            }
-        }
-
-        err = set_sched_policy(t_pid, sp);
+        err = SetTaskProfiles(t_pid, {kCpusetProfileMap.at(grp)}, true) ? 0 : -1;
         if (err != NO_ERROR) {
             signalExceptionForGroupError(env, -err, t_pid);
             break;
diff --git a/core/jni/android_view_RenderNode.cpp b/core/jni/android_view_RenderNode.cpp
index 222a873..538861e 100644
--- a/core/jni/android_view_RenderNode.cpp
+++ b/core/jni/android_view_RenderNode.cpp
@@ -52,9 +52,14 @@
     renderNode->output();
 }
 
-static jint android_view_RenderNode_getDebugSize(JNIEnv* env, jobject clazz, jlong renderNodePtr) {
+static jint android_view_RenderNode_getUsageSize(JNIEnv* env, jobject clazz, jlong renderNodePtr) {
     RenderNode* renderNode = reinterpret_cast<RenderNode*>(renderNodePtr);
-    return renderNode->getDebugSize();
+    return renderNode->getUsageSize();
+}
+
+static jint android_view_RenderNode_getAllocatedSize(JNIEnv* env, jobject clazz, jlong renderNodePtr) {
+    RenderNode* renderNode = reinterpret_cast<RenderNode*>(renderNodePtr);
+    return renderNode->getAllocatedSize();
 }
 
 static jlong android_view_RenderNode_create(JNIEnv* env, jobject, jstring name) {
@@ -647,7 +652,8 @@
     { "nCreate",               "(Ljava/lang/String;)J", (void*) android_view_RenderNode_create },
     { "nGetNativeFinalizer",   "()J",    (void*) android_view_RenderNode_getNativeFinalizer },
     { "nOutput",               "(J)V",    (void*) android_view_RenderNode_output },
-    { "nGetDebugSize",         "(J)I",    (void*) android_view_RenderNode_getDebugSize },
+    { "nGetUsageSize",         "(J)I",    (void*) android_view_RenderNode_getUsageSize },
+    { "nGetAllocatedSize",         "(J)I",    (void*) android_view_RenderNode_getAllocatedSize },
     { "nAddAnimator",              "(JJ)V", (void*) android_view_RenderNode_addAnimator },
     { "nEndAllAnimators",          "(J)V", (void*) android_view_RenderNode_endAllAnimators },
     { "nRequestPositionUpdates",   "(JLandroid/graphics/RenderNode$PositionUpdateListener;)V", (void*) android_view_RenderNode_requestPositionUpdates },
diff --git a/core/jni/android_view_SurfaceControl.cpp b/core/jni/android_view_SurfaceControl.cpp
index 1ca9383..d5cd278 100644
--- a/core/jni/android_view_SurfaceControl.cpp
+++ b/core/jni/android_view_SurfaceControl.cpp
@@ -1244,6 +1244,15 @@
     return reinterpret_cast<jlong>(transaction.release());
 }
 
+static jlong nativeMirrorSurface(JNIEnv* env, jclass clazz, jlong mirrorOfObj) {
+    sp<SurfaceComposerClient> client = SurfaceComposerClient::getDefault();
+    SurfaceControl *mirrorOf = reinterpret_cast<SurfaceControl*>(mirrorOfObj);
+    sp<SurfaceControl> surface = client->mirrorSurface(mirrorOf);
+
+    surface->incStrong((void *)nativeCreate);
+    return reinterpret_cast<jlong>(surface.get());
+}
+
 // ----------------------------------------------------------------------------
 
 static const JNINativeMethod sSurfaceControlMethods[] = {
@@ -1394,6 +1403,8 @@
             (void*)nativeReadTransactionFromParcel },
     {"nativeWriteTransactionToParcel", "(JLandroid/os/Parcel;)V",
             (void*)nativeWriteTransactionToParcel },
+    {"nativeMirrorSurface", "(J)J",
+            (void*)nativeMirrorSurface },
 };
 
 int register_android_view_SurfaceControl(JNIEnv* env)
diff --git a/core/proto/android/server/activitymanagerservice.proto b/core/proto/android/server/activitymanagerservice.proto
index d54b6b0..d01a45c 100644
--- a/core/proto/android/server/activitymanagerservice.proto
+++ b/core/proto/android/server/activitymanagerservice.proto
@@ -118,13 +118,15 @@
 message ActivityRecordProto {
     option (.android.msg_privacy).dest = DEST_AUTOMATIC;
 
-    optional .com.android.server.wm.ConfigurationContainerProto configuration_container = 1;
+    // To be removed soon.
+    optional .com.android.server.wm.ConfigurationContainerProto configuration_container = 1 [deprecated=true];
     optional .com.android.server.wm.IdentifierProto identifier = 2;
     optional string state = 3;
     optional bool visible = 4;
     optional bool front_of_task = 5;
     optional int32 proc_id = 6;
     optional bool translucent = 7;
+    optional .com.android.server.wm.AppWindowTokenProto app_window_token = 8;
 }
 
 message KeyguardControllerProto {
diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml
index 7a0d0cb..b030b33 100644
--- a/core/res/AndroidManifest.xml
+++ b/core/res/AndroidManifest.xml
@@ -794,6 +794,18 @@
         android:permissionFlags="hardRestricted"
         android:protectionLevel="dangerous" />
 
+    <!-- @SystemApi @TestApi Allows an application to forward cell broadcast messages to the cell
+         broadcast module. This is required in order to bind to the cell broadcast service, and
+         ensures that only the system can forward messages to it.
+
+         <p>Protection level: signature
+
+         @hide -->
+    <permission android:name="android.permission.BIND_CELL_BROADCAST_SERVICE"
+        android:label="@string/permlab_bindCellBroadcastService"
+        android:description="@string/permdesc_bindCellBroadcastService"
+        android:protectionLevel="signature" />
+
     <!-- @SystemApi @TestApi Allows an application to read previously received cell broadcast
          messages and to register a content observer to get notifications when
          a cell broadcast has been received and added to the database. For
@@ -2552,19 +2564,6 @@
         android:label="@string/permlab_readSyncStats"
         android:protectionLevel="normal" />
 
-    <!-- ==================================================== -->
-    <!-- Permissions related to accessibility                 -->
-    <!-- ==================================================== -->
-    <eat-comment />
-
-    <!-- Allows applications to define the accessibility shortcut target.
-         <p>Protection level: normal
-    -->
-    <permission android:name="android.permission.ACCESSIBILITY_SHORTCUT_TARGET"
-                android:description="@string/permdesc_accessibilityShortcutTarget"
-                android:label="@string/permlab_accessibilityShortcutTarget"
-                android:protectionLevel="normal" />
-
     <!-- ============================================ -->
     <!-- Permissions for low-level system interaction -->
     <!-- ============================================ -->
diff --git a/core/res/res/values-af/strings.xml b/core/res/res/values-af/strings.xml
index 0e0f34a..dd9eafe 100644
--- a/core/res/res/values-af/strings.xml
+++ b/core/res/res/values-af/strings.xml
@@ -344,6 +344,10 @@
     <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_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>
@@ -1077,7 +1081,7 @@
     <string name="Midnight" msgid="5630806906897892201">"Middernag"</string>
     <string name="elapsed_time_short_format_mm_ss" msgid="4431555943828711473">"<xliff:g id="MINUTES">%1$02d</xliff:g>:<xliff:g id="SECONDS">%2$02d</xliff:g>"</string>
     <string name="elapsed_time_short_format_h_mm_ss" msgid="1846071997616654124">"<xliff:g id="HOURS">%1$d</xliff:g>:<xliff:g id="MINUTES">%2$02d</xliff:g>:<xliff:g id="SECONDS">%3$02d</xliff:g>"</string>
-    <string name="selectAll" msgid="6876518925844129331">"Kies alle"</string>
+    <string name="selectAll" msgid="6876518925844129331">"Kies alles"</string>
     <string name="cut" msgid="3092569408438626261">"Sny"</string>
     <string name="copy" msgid="2681946229533511987">"Kopieer"</string>
     <string name="failed_to_copy_to_clipboard" msgid="1833662432489814471">"Kon nie na knipbord toe kopieer nie"</string>
@@ -1358,7 +1362,7 @@
     <string name="usb_power_notification_message" msgid="4647527153291917218">"Laai tans gekoppelde toestel. Tik vir meer opsies."</string>
     <string name="usb_unsupported_audio_accessory_title" msgid="3529881374464628084">"Analoë oudiobykomstigheid bespeur"</string>
     <string name="usb_unsupported_audio_accessory_message" msgid="6309553946441565215">"Die aangehegde toestel is nie met hierdie foon versoenbaar nie. Tik om meer te wete te kom."</string>
-    <string name="adb_active_notification_title" msgid="6729044778949189918">"USB-ontfouter gekoppel"</string>
+    <string name="adb_active_notification_title" msgid="6729044778949189918">"USB-ontfouting gekoppel"</string>
     <string name="adb_active_notification_message" msgid="7463062450474107752">"Tik om USB-ontfouting af te skakel"</string>
     <string name="adb_active_notification_message" product="tv" msgid="8470296818270110396">"Kies om USB-ontfouting te deaktiveer."</string>
     <string name="test_harness_mode_notification_title" msgid="2216359742631914387">"Toetsraamwerkmodus is geaktiveer"</string>
diff --git a/core/res/res/values-am/strings.xml b/core/res/res/values-am/strings.xml
index eec1b22..a007c9d 100644
--- a/core/res/res/values-am/strings.xml
+++ b/core/res/res/values-am/strings.xml
@@ -344,6 +344,10 @@
     <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_readCellBroadcasts" msgid="1598328843619646166">"የህዋስ ስርጭት መልዕክቶችን አንብብ"</string>
     <string name="permdesc_readCellBroadcasts" msgid="6361972776080458979">"መሣሪያህ የህዋስ ስርጭት መልዕክቶች ሲቀበል መተግበሪያው እንዲያነበው ይፈቅድለታል። የህዋስ ስርጭት ማንቂያዎች አስቸኳይ ሁኔታዎች ሲያጋጥሙ አንዳንድ አካባቢዎች ላይ የሚላኩ ናቸው። የህዋስ ስርጭት ሲደርስ ተንኮል አዘል መተግበሪያዎች በመሣሪያህ አፈጻጸም ወይም አሰራር ላይ ጣልቃ ሊገቡ ይችላሉ።"</string>
     <string name="permlab_subscribedFeedsRead" msgid="4756609637053353318">"የምዝገባ መግቦች አንበብ"</string>
diff --git a/core/res/res/values-ar/strings.xml b/core/res/res/values-ar/strings.xml
index d195d74..2e272ee 100644
--- a/core/res/res/values-ar/strings.xml
+++ b/core/res/res/values-ar/strings.xml
@@ -356,6 +356,10 @@
     <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_readCellBroadcasts" msgid="1598328843619646166">"قراءة رسائل بث الخلية"</string>
     <string name="permdesc_readCellBroadcasts" msgid="6361972776080458979">"السماح للتطبيق بقراءة رسائل بث الخلية التي يتلقاها هذا الجهاز. يتم تسليم اشعارات بث الخلية في بعض المواقع لتحذيرك من حالات طارئة. يمكن أن تتداخل التطبيقات الضارة مع أداء أو تشغيل الجهاز عندما يتم تلقي بث خلية طارئ."</string>
     <string name="permlab_subscribedFeedsRead" msgid="4756609637053353318">"قراءة الخلاصات المشتركة"</string>
@@ -1157,7 +1161,7 @@
     <string name="Midnight" msgid="5630806906897892201">"منتصف الليل"</string>
     <string name="elapsed_time_short_format_mm_ss" msgid="4431555943828711473">"<xliff:g id="MINUTES">%1$02d</xliff:g>:<xliff:g id="SECONDS">%2$02d</xliff:g>"</string>
     <string name="elapsed_time_short_format_h_mm_ss" msgid="1846071997616654124">"<xliff:g id="HOURS">%1$d</xliff:g>:<xliff:g id="MINUTES">%2$02d</xliff:g>:<xliff:g id="SECONDS">%3$02d</xliff:g>"</string>
-    <string name="selectAll" msgid="6876518925844129331">"تحديد الكل"</string>
+    <string name="selectAll" msgid="6876518925844129331">"اختيار الكل"</string>
     <string name="cut" msgid="3092569408438626261">"قص"</string>
     <string name="copy" msgid="2681946229533511987">"نسخ"</string>
     <string name="failed_to_copy_to_clipboard" msgid="1833662432489814471">"تعذّر النسخ في الحافظة"</string>
@@ -1446,8 +1450,8 @@
     <string name="usb_power_notification_message" msgid="4647527153291917218">"جارٍ شحن الجهاز المتصل. انقر لعرض خيارات أكثر."</string>
     <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_title" msgid="6729044778949189918">"‏تم توصيل تصحيح أخطاء الجهاز عبر 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>
diff --git a/core/res/res/values-as/strings.xml b/core/res/res/values-as/strings.xml
index aa2fbc5..70d9713 100644
--- a/core/res/res/values-as/strings.xml
+++ b/core/res/res/values-as/strings.xml
@@ -344,6 +344,10 @@
     <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_readCellBroadcasts" msgid="1598328843619646166">"চেল সম্প্ৰচাৰৰ বার্তাবোৰ পঢ়ক"</string>
     <string name="permdesc_readCellBroadcasts" msgid="6361972776080458979">"আপোনাৰ ডিভাইচে লাভ কৰা চেল সম্প্ৰচাৰৰ বার্তাবোৰ পঢ়িবলৈ এপক অনুমতি দিয়ে। আপোনাক জৰুৰীকালীন পৰিস্থিতিবোৰত সর্তক কৰিবলৈ চেল সম্প্ৰচাৰৰ বার্তাবোৰ প্ৰেৰণ কৰা হয়। জৰুৰীকালীন চেল সম্প্ৰচাৰ লাভ কৰাৰ সময়ত আপোনাৰ ডিভাইচৰ কাৰ্যদক্ষতা বা কাৰ্যপ্ৰণালীত ক্ষতিকাৰক এপবোৰে হস্তক্ষেপ কৰিব পাৰে।"</string>
     <string name="permlab_subscribedFeedsRead" msgid="4756609637053353318">"আপুনি সদস্যভুক্ত হোৱা ফীডসমূহ পঢ়ক"</string>
diff --git a/core/res/res/values-az/strings.xml b/core/res/res/values-az/strings.xml
index 5709bfd..5d09250 100644
--- a/core/res/res/values-az/strings.xml
+++ b/core/res/res/values-az/strings.xml
@@ -344,6 +344,10 @@
     <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_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>
diff --git a/core/res/res/values-b+sr+Latn/strings.xml b/core/res/res/values-b+sr+Latn/strings.xml
index 0e33329..5891bae 100644
--- a/core/res/res/values-b+sr+Latn/strings.xml
+++ b/core/res/res/values-b+sr+Latn/strings.xml
@@ -347,6 +347,10 @@
     <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_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>
diff --git a/core/res/res/values-be/strings.xml b/core/res/res/values-be/strings.xml
index 662290d..6fdc8f1 100644
--- a/core/res/res/values-be/strings.xml
+++ b/core/res/res/values-be/strings.xml
@@ -350,6 +350,10 @@
     <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_readCellBroadcasts" msgid="1598328843619646166">"чытаць паведамленні базавай станцыі"</string>
     <string name="permdesc_readCellBroadcasts" msgid="6361972776080458979">"Дазваляе прыкладанню чытаць паведамленні базавай станцыі, атрыманыя прыладай. Папярэджанні базавай станцыі дасылаюцца ў некаторыя месцы, каб папярэдзіць вас аб надзвычайных сітуацыях. Шкоднасныя прыкладанні могуць уплываць на прадукцыйнасць ці працу прылады пры атрыманні паведамлення базавай станцыі аб надзвычайнай сітуацыі."</string>
     <string name="permlab_subscribedFeedsRead" msgid="4756609637053353318">"чытаць падпісаныя каналы"</string>
@@ -1408,7 +1412,7 @@
     <string name="test_harness_mode_notification_title" msgid="2216359742631914387">"Тэставы рэжым уключаны"</string>
     <string name="test_harness_mode_notification_message" msgid="1343197173054407119">"Каб выключыць тэставы рэжым, скіньце налады да заводскіх значэнняў."</string>
     <string name="console_running_notification_title" msgid="4955436518220103382">"Паслядоўная кансоль уключана"</string>
-    <string name="console_running_notification_message" msgid="1331995933976263865">"Змянілася эфектыўнасць. Каб выключыць, праверце загрузчык."</string>
+    <string name="console_running_notification_message" msgid="1331995933976263865">"Паказчык эфектыўнасці змяніўся. Каб выключыць кансоль, праверце загрузчык."</string>
     <string name="usb_contaminant_detected_title" msgid="7136400633704058349">"Вадкасць або смецце ў порце USB"</string>
     <string name="usb_contaminant_detected_message" msgid="832337061059487250">"Порт USB аўтаматычна адключаны. Каб даведацца больш, націсніце тут."</string>
     <string name="usb_contaminant_not_detected_title" msgid="7708281124088684821">"Порт USB можна выкарыстоўваць"</string>
diff --git a/core/res/res/values-bg/strings.xml b/core/res/res/values-bg/strings.xml
index 28949d1..e5fb7e8 100644
--- a/core/res/res/values-bg/strings.xml
+++ b/core/res/res/values-bg/strings.xml
@@ -344,6 +344,10 @@
     <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_readCellBroadcasts" msgid="1598328843619646166">"четене на съобщения с клетъчно излъчване"</string>
     <string name="permdesc_readCellBroadcasts" msgid="6361972776080458979">"Разрешава на приложението да чете съобщения с клетъчно излъчване, получени от устройството ви. Сигналите с клетъчно излъчване се получават на някои местоположения, за да ви предупредят за спешни ситуации. Злонамерените приложения могат да възпрепятстват изпълнението или работата на устройството ви при получаване на такова спешно излъчване."</string>
     <string name="permlab_subscribedFeedsRead" msgid="4756609637053353318">"четене на емисиите с абонамент"</string>
diff --git a/core/res/res/values-bn/strings.xml b/core/res/res/values-bn/strings.xml
index f88e778..651ed4d 100644
--- a/core/res/res/values-bn/strings.xml
+++ b/core/res/res/values-bn/strings.xml
@@ -344,6 +344,10 @@
     <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_readCellBroadcasts" msgid="1598328843619646166">"সেল সম্প্রচার মেসেজ পড়ুন"</string>
     <string name="permdesc_readCellBroadcasts" msgid="6361972776080458979">"আপনার ডিভাইস দ্বারা প্রাপ্ত সেল সম্প্রচার পড়তে অ্যাপ্লিকেশানটিকে অনুমতি দেয়৷ কয়েকটি স্থানে আপনাকে জরুরি অবস্থার জন্য সতর্ক করতে জরুরি সতর্কতাগুলি বিতরণ করা হয়৷ যখন একটি জরুরি সেল সম্প্রচার প্রাপ্ত হয় তখন ক্ষতিকারক অ্যাপ্লিকেশানগুলি আপনার ডিভাইসের কার্য সম্পাদনা বা কার্যকলাপে প্রতিবন্ধকতার সৃষ্টি করতে পারে৷"</string>
     <string name="permlab_subscribedFeedsRead" msgid="4756609637053353318">"গ্রাহক হিসেবে নেওয়া ফিডগুলি পড়ে"</string>
diff --git a/core/res/res/values-bs/strings.xml b/core/res/res/values-bs/strings.xml
index ae075cc..0695fb8 100644
--- a/core/res/res/values-bs/strings.xml
+++ b/core/res/res/values-bs/strings.xml
@@ -347,6 +347,10 @@
     <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_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>
diff --git a/core/res/res/values-ca/strings.xml b/core/res/res/values-ca/strings.xml
index 0427569..8ef9a17 100644
--- a/core/res/res/values-ca/strings.xml
+++ b/core/res/res/values-ca/strings.xml
@@ -344,6 +344,10 @@
     <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_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>
diff --git a/core/res/res/values-cs/strings.xml b/core/res/res/values-cs/strings.xml
index 32dac4d..72e7a86 100644
--- a/core/res/res/values-cs/strings.xml
+++ b/core/res/res/values-cs/strings.xml
@@ -350,6 +350,10 @@
     <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_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>
diff --git a/core/res/res/values-da/strings.xml b/core/res/res/values-da/strings.xml
index 3d79588..88900a0 100644
--- a/core/res/res/values-da/strings.xml
+++ b/core/res/res/values-da/strings.xml
@@ -344,6 +344,10 @@
     <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_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>
diff --git a/core/res/res/values-de/strings.xml b/core/res/res/values-de/strings.xml
index cbba324..6bf5404 100644
--- a/core/res/res/values-de/strings.xml
+++ b/core/res/res/values-de/strings.xml
@@ -344,6 +344,10 @@
     <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_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>
diff --git a/core/res/res/values-el/strings.xml b/core/res/res/values-el/strings.xml
index e162d6b..3570fc1 100644
--- a/core/res/res/values-el/strings.xml
+++ b/core/res/res/values-el/strings.xml
@@ -344,6 +344,10 @@
     <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_readCellBroadcasts" msgid="1598328843619646166">"διαβάζει μηνύματα που έχουν μεταδοθεί μέσω κινητού τηλεφώνου"</string>
     <string name="permdesc_readCellBroadcasts" msgid="6361972776080458979">"Επιτρέπει στην εφαρμογή την ανάγνωση μηνυμάτων που έχουν μεταδοθεί μέσω κινητού τηλεφώνου και έχουν ληφθεί από τη συσκευή σας. Ειδοποιήσεις που μεταδίδονται μέσω κινητού παραδίδονται σε ορισμένες τοποθεσίες για να σας προειδοποιήσουν για καταστάσεις έκτακτης ανάγκης. Κακόβουλες εφαρμογές ενδέχεται να παρεμποδίσουν την απόδοση ή τη λειτουργία της συσκευής σας κατά τη λήψη μετάδοσης μέσω κινητού σχετικά με μια επείγουσα κατάσταση."</string>
     <string name="permlab_subscribedFeedsRead" msgid="4756609637053353318">"διαβάζει ροές δεδομένων στις οποίες έχετε εγγραφεί"</string>
diff --git a/core/res/res/values-en-rAU/strings.xml b/core/res/res/values-en-rAU/strings.xml
index 56d09f3..e1d9875 100644
--- a/core/res/res/values-en-rAU/strings.xml
+++ b/core/res/res/values-en-rAU/strings.xml
@@ -344,6 +344,10 @@
     <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_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>
diff --git a/core/res/res/values-en-rCA/strings.xml b/core/res/res/values-en-rCA/strings.xml
index 2aafb7a..56b54d9 100644
--- a/core/res/res/values-en-rCA/strings.xml
+++ b/core/res/res/values-en-rCA/strings.xml
@@ -344,6 +344,10 @@
     <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_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>
diff --git a/core/res/res/values-en-rGB/strings.xml b/core/res/res/values-en-rGB/strings.xml
index 56d09f3..e1d9875 100644
--- a/core/res/res/values-en-rGB/strings.xml
+++ b/core/res/res/values-en-rGB/strings.xml
@@ -344,6 +344,10 @@
     <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_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>
diff --git a/core/res/res/values-en-rIN/strings.xml b/core/res/res/values-en-rIN/strings.xml
index 56d09f3..e1d9875 100644
--- a/core/res/res/values-en-rIN/strings.xml
+++ b/core/res/res/values-en-rIN/strings.xml
@@ -344,6 +344,10 @@
     <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_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>
diff --git a/core/res/res/values-en-rXC/strings.xml b/core/res/res/values-en-rXC/strings.xml
index 9844b67..c4d3157 100644
--- a/core/res/res/values-en-rXC/strings.xml
+++ b/core/res/res/values-en-rXC/strings.xml
@@ -344,6 +344,10 @@
     <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_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>
diff --git a/core/res/res/values-es-rUS/strings.xml b/core/res/res/values-es-rUS/strings.xml
index 7289f4b..30f8ba7 100644
--- a/core/res/res/values-es-rUS/strings.xml
+++ b/core/res/res/values-es-rUS/strings.xml
@@ -344,6 +344,10 @@
     <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_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>
@@ -1359,7 +1363,7 @@
     <string name="usb_unsupported_audio_accessory_title" msgid="3529881374464628084">"Se detectó un accesorio de audio analógico"</string>
     <string name="usb_unsupported_audio_accessory_message" msgid="6309553946441565215">"El dispositivo adjunto no es compatible con este teléfono. Presiona para obtener más información."</string>
     <string name="adb_active_notification_title" msgid="6729044778949189918">"Depuración por USB conectada"</string>
-    <string name="adb_active_notification_message" msgid="7463062450474107752">"Presiona para desactivar la depuración USB"</string>
+    <string name="adb_active_notification_message" msgid="7463062450474107752">"Presiona para desactivar la depuración por USB"</string>
     <string name="adb_active_notification_message" product="tv" msgid="8470296818270110396">"Seleccionar para desactivar la depuración por USB"</string>
     <string name="test_harness_mode_notification_title" msgid="2216359742631914387">"Se habilitó el modo de agente de prueba"</string>
     <string name="test_harness_mode_notification_message" msgid="1343197173054407119">"Restablece la configuración de fábrica para inhabilitar el modo de agente de prueba."</string>
diff --git a/core/res/res/values-es/strings.xml b/core/res/res/values-es/strings.xml
index c513b39..15e662c 100644
--- a/core/res/res/values-es/strings.xml
+++ b/core/res/res/values-es/strings.xml
@@ -344,6 +344,10 @@
     <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_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>
diff --git a/core/res/res/values-et/strings.xml b/core/res/res/values-et/strings.xml
index d70a580..093f7d7 100644
--- a/core/res/res/values-et/strings.xml
+++ b/core/res/res/values-et/strings.xml
@@ -344,6 +344,10 @@
     <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_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>
diff --git a/core/res/res/values-eu/strings.xml b/core/res/res/values-eu/strings.xml
index 3a9cb13..53b1a38 100644
--- a/core/res/res/values-eu/strings.xml
+++ b/core/res/res/values-eu/strings.xml
@@ -280,37 +280,37 @@
     <string name="managed_profile_label" msgid="8947929265267690522">"Aldatu laneko profilera"</string>
     <string name="permgrouplab_contacts" msgid="3657758145679177612">"Kontaktuak"</string>
     <string name="permgroupdesc_contacts" msgid="6951499528303668046">"atzitu kontaktuak"</string>
-    <string name="permgrouprequest_contacts" msgid="6032805601881764300">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; aplikazioari kontaktuak atzitzeko baimena eman nahi diozu?"</string>
+    <string name="permgrouprequest_contacts" msgid="6032805601881764300">"Kontaktuak atzitzeko baimena eman nahi diozu &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; aplikazioari?"</string>
     <string name="permgrouplab_location" msgid="7275582855722310164">"Kokapena"</string>
     <string name="permgroupdesc_location" msgid="1346617465127855033">"atzitu gailuaren kokapena"</string>
-    <string name="permgrouprequest_location" msgid="3788275734953323491">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; aplikazioari gailuaren kokapena atzitzeko baimena eman nahi diozu?"</string>
+    <string name="permgrouprequest_location" msgid="3788275734953323491">"Gailuaren kokapena atzitzeko baimena eman nahi diozu &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; aplikazioari?"</string>
     <string name="permgrouprequestdetail_location" msgid="1347189607421252902">"Hura erabiltzen ari zarenean soilik atzituko du aplikazioak kokapena"</string>
-    <string name="permgroupbackgroundrequest_location" msgid="5039063878675613235">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; aplikazioari gailuaren kokapena &lt;b&gt;beti&lt;/b&gt; atzitzeko baimena eman nahi diozu?"</string>
+    <string name="permgroupbackgroundrequest_location" msgid="5039063878675613235">"Gailuaren kokapena &lt;b&gt;beti&lt;/b&gt; atzitzeko baimena eman nahi diozu &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; aplikazioari?"</string>
     <string name="permgroupbackgroundrequestdetail_location" msgid="4597006851453417387">"Aplikazioak hura darabilzunean atzi dezake kokapena"</string>
     <string name="permgrouplab_calendar" msgid="5863508437783683902">"Egutegia"</string>
     <string name="permgroupdesc_calendar" msgid="3889615280211184106">"atzitu egutegia"</string>
-    <string name="permgrouprequest_calendar" msgid="289900767793189421">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; aplikazioari egutegia atzitzeko baimena eman nahi diozu?"</string>
+    <string name="permgrouprequest_calendar" msgid="289900767793189421">"Egutegia atzitzeko baimena eman nahi diozu &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; aplikazioari?"</string>
     <string name="permgrouplab_sms" msgid="228308803364967808">"SMS mezuak"</string>
     <string name="permgroupdesc_sms" msgid="4656988620100940350">"bidali eta ikusi SMS mezuak"</string>
-    <string name="permgrouprequest_sms" msgid="7168124215838204719">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; aplikazioari SMS mezuak bidaltzeko eta ikusteko baimena eman nahi diozu?"</string>
+    <string name="permgrouprequest_sms" msgid="7168124215838204719">"SMS mezuak bidaltzeko eta ikusteko baimena eman nahi diozu &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; aplikazioari?"</string>
     <string name="permgrouplab_storage" msgid="1971118770546336966">"Memoria"</string>
     <string name="permgroupdesc_storage" msgid="637758554581589203">"atzitu gailuko argazkiak, multimedia-edukia eta fitxategiak"</string>
-    <string name="permgrouprequest_storage" msgid="7885942926944299560">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; aplikazioari gailuko argazkiak, multimedia-edukia eta fitxategiak atzitzeko baimena eman nahi diozu?"</string>
+    <string name="permgrouprequest_storage" msgid="7885942926944299560">"Gailuko argazkiak, multimedia-edukia eta fitxategiak atzitzeko baimena eman nahi diozu &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; aplikazioari?"</string>
     <string name="permgrouplab_microphone" msgid="171539900250043464">"Mikrofonoa"</string>
     <string name="permgroupdesc_microphone" msgid="4988812113943554584">"grabatu audioa"</string>
-    <string name="permgrouprequest_microphone" msgid="9167492350681916038">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; aplikazioari audioa grabatzeko baimena eman nahi diozu?"</string>
+    <string name="permgrouprequest_microphone" msgid="9167492350681916038">"Audioa grabatzeko baimena eman nahi diozu &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; aplikazioari?"</string>
     <string name="permgrouplab_activityRecognition" msgid="1565108047054378642">"Ariketa fisikoa"</string>
     <string name="permgroupdesc_activityRecognition" msgid="6949472038320473478">"ariketa fisikoak atzitu"</string>
     <string name="permgrouprequest_activityRecognition" msgid="7626438016904799383">"Zure ariketa fisikoak atzitzeko baimena eman nahi diozu &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; aplikazioari?"</string>
     <string name="permgrouplab_camera" msgid="4820372495894586615">"Kamera"</string>
     <string name="permgroupdesc_camera" msgid="3250611594678347720">"atera argazkiak eta grabatu bideoak"</string>
-    <string name="permgrouprequest_camera" msgid="1299833592069671756">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; aplikazioari argazkiak ateratzeko eta bideoak grabatzeko baimena eman nahi diozu?"</string>
+    <string name="permgrouprequest_camera" msgid="1299833592069671756">"Argazkiak ateratzeko eta bideoak grabatzeko baimena eman nahi diozu &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; aplikazioari?"</string>
     <string name="permgrouplab_calllog" msgid="8798646184930388160">"Deien erregistroa"</string>
     <string name="permgroupdesc_calllog" msgid="3006237336748283775">"irakurri telefonoko deien erregistroa eta idatzi bertan"</string>
-    <string name="permgrouprequest_calllog" msgid="8487355309583773267">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; aplikazioari telefonoko deien erregistroa atzitzeko baimena eman nahi diozu?"</string>
+    <string name="permgrouprequest_calllog" msgid="8487355309583773267">"Telefonoko deien erregistroa atzitzeko baimena eman nahi diozu &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; aplikazioari?"</string>
     <string name="permgrouplab_phone" msgid="5229115638567440675">"Telefonoa"</string>
     <string name="permgroupdesc_phone" msgid="6234224354060641055">"egin eta kudeatu telefono-deiak"</string>
-    <string name="permgrouprequest_phone" msgid="9166979577750581037">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; aplikazioari telefono-deiak egiteko eta kudeatzeko baimena eman nahi diozu?"</string>
+    <string name="permgrouprequest_phone" msgid="9166979577750581037">"Telefono-deiak egiteko eta kudeatzeko baimena eman nahi diozu &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; aplikazioari?"</string>
     <string name="permgrouplab_sensors" msgid="4838614103153567532">"Gorputz-sentsoreak"</string>
     <string name="permgroupdesc_sensors" msgid="7147968539346634043">"atzitu bizi-konstanteei buruzko sentsorearen datuak"</string>
     <string name="permgrouprequest_sensors" msgid="6349806962814556786">"Bizi-konstanteei buruzko sentsorearen datuak atzitzeko baimena eman nahi diozu &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; aplikazioari?"</string>
@@ -344,6 +344,10 @@
     <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_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>
@@ -1895,8 +1899,8 @@
     <string name="default_notification_channel_label" msgid="5929663562028088222">"Kategoriarik gabea"</string>
     <string name="importance_from_user" msgid="7318955817386549931">"Zuk ezarri duzu jakinarazpen hauen garrantzia."</string>
     <string name="importance_from_person" msgid="9160133597262938296">"Garrantzitsua da eragiten dien pertsonengatik."</string>
-    <string name="user_creation_account_exists" msgid="6559477114648176531">"<xliff:g id="APP">%1$s</xliff:g> aplikazioari <xliff:g id="ACCOUNT">%2$s</xliff:g> kontua duen erabiltzailea sortzeko baimena eman nahi diozu? (Badago kontu hori duen erabiltzaile bat)"</string>
-    <string name="user_creation_adding" msgid="9089159170398841763">"<xliff:g id="APP">%1$s</xliff:g> aplikazioari <xliff:g id="ACCOUNT">%2$s</xliff:g> kontua duen erabiltzailea sortzeko baimena eman nahi diozu?"</string>
+    <string name="user_creation_account_exists" msgid="6559477114648176531">"<xliff:g id="ACCOUNT">%2$s</xliff:g> kontua duen erabiltzailea sortzeko baimena eman nahi diozu <xliff:g id="APP">%1$s</xliff:g> aplikazioari? (Badago kontu hori duen erabiltzaile bat)"</string>
+    <string name="user_creation_adding" msgid="9089159170398841763">"<xliff:g id="ACCOUNT">%2$s</xliff:g> kontua duen erabiltzailea sortzeko baimena eman nahi diozu <xliff:g id="APP">%1$s</xliff:g> aplikazioari?"</string>
     <string name="language_selection_title" msgid="2680677278159281088">"Gehitu hizkuntza"</string>
     <string name="country_selection_title" msgid="2954859441620215513">"Lurralde-hobespena"</string>
     <string name="search_language_hint" msgid="7042102592055108574">"Adierazi hizkuntza"</string>
diff --git a/core/res/res/values-fa/strings.xml b/core/res/res/values-fa/strings.xml
index f0ea22d..2b849d5 100644
--- a/core/res/res/values-fa/strings.xml
+++ b/core/res/res/values-fa/strings.xml
@@ -344,6 +344,10 @@
     <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_readCellBroadcasts" msgid="1598328843619646166">"خواندن پیام‌های پخش سلولی"</string>
     <string name="permdesc_readCellBroadcasts" msgid="6361972776080458979">"‏به برنامه اجازه می‎دهد پیام‌های پخش سلولی دستگاه شما را بخواند. هشدارهای پخش سلولی در برخی از موقعیت‌های مکانی تحویل داده می‎شوند تا موقعیت‌های اضطراری را به شما اعلام کنند. وقتی پخش سلولی دریافت می‎شود، ممکن است برنامه‎های مخرب در عملکرد یا کارکرد دستگاه شما اختلال ایجاد کنند."</string>
     <string name="permlab_subscribedFeedsRead" msgid="4756609637053353318">"خواندن فیدهای مشترک"</string>
diff --git a/core/res/res/values-fi/strings.xml b/core/res/res/values-fi/strings.xml
index b1648f5..c18e5bf 100644
--- a/core/res/res/values-fi/strings.xml
+++ b/core/res/res/values-fi/strings.xml
@@ -344,6 +344,10 @@
     <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_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>
@@ -1633,7 +1637,7 @@
     <string name="kg_pattern_instructions" msgid="398978611683075868">"Piirrä kuvio"</string>
     <string name="kg_sim_pin_instructions" msgid="2319508550934557331">"Anna SIM-kortin PIN-koodi"</string>
     <string name="kg_pin_instructions" msgid="2377242233495111557">"Anna PIN-koodi"</string>
-    <string name="kg_password_instructions" msgid="5753646556186936819">"Anna salasana"</string>
+    <string name="kg_password_instructions" msgid="5753646556186936819">"Lisää salasana"</string>
     <string name="kg_puk_enter_puk_hint" msgid="453227143861735537">"SIM-kortti on nyt poistettu käytöstä. Jatka antamalla PUK-koodi. Saat lisätietoja ottamalla yhteyttä operaattoriin."</string>
     <string name="kg_puk_enter_pin_hint" msgid="7871604527429602024">"Anna haluamasi PIN-koodi"</string>
     <string name="kg_enter_confirm_pin_hint" msgid="325676184762529976">"Vahvista haluamasi PIN-koodi"</string>
diff --git a/core/res/res/values-fr-rCA/strings.xml b/core/res/res/values-fr-rCA/strings.xml
index 384f5fa..3bd5c23 100644
--- a/core/res/res/values-fr-rCA/strings.xml
+++ b/core/res/res/values-fr-rCA/strings.xml
@@ -344,6 +344,10 @@
     <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_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>
@@ -530,9 +534,9 @@
     <string name="biometric_not_recognized" msgid="5770511773560736082">"Données biométriques non reconnues"</string>
     <string name="biometric_error_canceled" msgid="349665227864885880">"Authentification annulée"</string>
     <string name="biometric_error_device_not_secured" msgid="6583143098363528349">"Aucun NIP, schéma ou mot de passe défini"</string>
-    <string name="fingerprint_acquired_partial" msgid="735082772341716043">"Empreinte digitale partielle détectée. Veuillez essayer de nouveau."</string>
+    <string name="fingerprint_acquired_partial" msgid="735082772341716043">"Empreinte digitale partielle 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 capteur d\'empreintes digitales est sale. Veuillez le nettoyer et essayer de nouveau."</string>
+    <string name="fingerprint_acquired_imager_dirty" msgid="1087209702421076105">"Le capteur d\'empreintes digitales est sale. Veuillez le nettoyer et réessayer."</string>
     <string name="fingerprint_acquired_too_fast" msgid="6470642383109155969">"Vous avez déplacé votre doigt trop rapidement. Veuillez réessayer."</string>
     <string name="fingerprint_acquired_too_slow" msgid="59250885689661653">"Vous avez déplacé votre doigt trop lentement. Veuillez réessayer."</string>
   <string-array name="fingerprint_acquired_vendor">
@@ -540,10 +544,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 le bouton Confirmer"</string>
-    <string name="fingerprint_error_hw_not_available" msgid="7955921658939936596">"Matériel d\'empreinte numérique indisponible."</string>
+    <string name="fingerprint_error_hw_not_available" msgid="7955921658939936596">"Matériel d\'empreinte digitale numérique indisponible."</string>
     <string name="fingerprint_error_no_space" msgid="1055819001126053318">"L\'empreinte digitale ne peut pas être enregistrée. Veuillez supprimer une empreinte existante."</string>
-    <string name="fingerprint_error_timeout" msgid="3927186043737732875">"Le temps attribué pour lire l\'empreinte est écoulé. Veuillez essayer de nouveau."</string>
-    <string name="fingerprint_error_canceled" msgid="4402024612660774395">"Opération d\'empreinte numérique annulée."</string>
+    <string name="fingerprint_error_timeout" msgid="3927186043737732875">"Le temps attribué pour lire l\'empreinte digitale est écoulé. Veuillez réessayer."</string>
+    <string name="fingerprint_error_canceled" msgid="4402024612660774395">"Opération d\'empreinte digitale numérique annulée."</string>
     <string name="fingerprint_error_user_canceled" msgid="7999639584615291494">"L\'opération d\'empreinte digitale a été 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. Capteur d\'empreintes digitales désactivé."</string>
@@ -1583,8 +1587,8 @@
     <string name="expires_on" msgid="3676242949915959821">"Expire le :"</string>
     <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 SHA-256 :"</string>
-    <string name="sha1_fingerprint" msgid="7930330235269404581">"Empreinte SHA-1 :"</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="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 d204ac1..8520c13 100644
--- a/core/res/res/values-fr/strings.xml
+++ b/core/res/res/values-fr/strings.xml
@@ -344,6 +344,10 @@
     <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_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>
diff --git a/core/res/res/values-gl/strings.xml b/core/res/res/values-gl/strings.xml
index b798bc5..78c7d03 100644
--- a/core/res/res/values-gl/strings.xml
+++ b/core/res/res/values-gl/strings.xml
@@ -344,6 +344,10 @@
     <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_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>
diff --git a/core/res/res/values-gu/strings.xml b/core/res/res/values-gu/strings.xml
index 5a41503..340245a 100644
--- a/core/res/res/values-gu/strings.xml
+++ b/core/res/res/values-gu/strings.xml
@@ -295,10 +295,10 @@
     <string name="permgrouprequest_sms" msgid="7168124215838204719">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt;ને SMS સંદેશા મોકલવા અને જોવાની મંજૂરી આપીએ?"</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>
+    <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>
@@ -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,6 +344,10 @@
     <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_readCellBroadcasts" msgid="1598328843619646166">"સેલ બ્રોડકાસ્ટ સંદેશા વાંચો"</string>
     <string name="permdesc_readCellBroadcasts" msgid="6361972776080458979">"એપ્લિકેશનને તમારા ઉપકરણ દ્વારા પ્રાપ્ત થયેલ સેલ બ્રોડકાસ્ટ સંદેશાને વાંચવાની મંજૂરી આપે છે. સેલ બ્રોડકાસ્ટ ચેતવણીઓ તમને કટોકટીની સ્થિતિઓ અંગે ચેતવવા માટે કેટલાક સ્થાનોમાં વિતરિત થાય છે. જ્યારે કટોકટીનો સેલ બ્રોડકાસ્ટ પ્રાપ્ત થાય ત્યારે દુર્ભાવનાપૂર્ણ ઍપ્લિકેશનો તમારા ઉપકરણના પ્રદર્શન અથવા ઓપરેશનમાં હસ્તક્ષેપ કરી શકે છે."</string>
     <string name="permlab_subscribedFeedsRead" msgid="4756609637053353318">"સબ્સ્ક્રાઇબ કરેલ ફીડ્સ વાંચો"</string>
@@ -513,9 +517,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>
@@ -1584,8 +1588,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-hi/strings.xml b/core/res/res/values-hi/strings.xml
index 5b90234..8f78f95 100644
--- a/core/res/res/values-hi/strings.xml
+++ b/core/res/res/values-hi/strings.xml
@@ -344,6 +344,10 @@
     <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_readCellBroadcasts" msgid="1598328843619646166">"सेल ब्रॉडकास्ट (CBC) मैसेज पढ़ें"</string>
     <string name="permdesc_readCellBroadcasts" msgid="6361972776080458979">"ऐप को, वो सेल ब्रॉडकास्ट (CBC) मैसेज पढ़ने देता है जो आपके डिवाइस को मिले हैं. सेल ब्रॉडकास्ट (CBC) अलर्ट कुछ स्थानों (लोकेशन) पर आपको आपातकालीन स्‍थितियों की चेतावनी देने के लिए दिए जाते हैं. आपातकालीन सेल ब्रॉडकास्ट (CBC) मिलने पर, धोखा देने वाले ऐप आपके डिवाइस के परफ़ॉर्मेंस या कार्यवाही में दखल दे सकते हैं."</string>
     <string name="permlab_subscribedFeedsRead" msgid="4756609637053353318">"सदस्यता वाली फ़ीड पढ़ें"</string>
diff --git a/core/res/res/values-hr/strings.xml b/core/res/res/values-hr/strings.xml
index 291b116..8ddd5f8 100644
--- a/core/res/res/values-hr/strings.xml
+++ b/core/res/res/values-hr/strings.xml
@@ -347,6 +347,10 @@
     <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_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>
diff --git a/core/res/res/values-hu/strings.xml b/core/res/res/values-hu/strings.xml
index f83ac69..d910025 100644
--- a/core/res/res/values-hu/strings.xml
+++ b/core/res/res/values-hu/strings.xml
@@ -344,6 +344,10 @@
     <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_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>
diff --git a/core/res/res/values-hy/strings.xml b/core/res/res/values-hy/strings.xml
index 2c40a5a..6f5507f 100644
--- a/core/res/res/values-hy/strings.xml
+++ b/core/res/res/values-hy/strings.xml
@@ -344,6 +344,10 @@
     <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_readCellBroadcasts" msgid="1598328843619646166">"կարդալ բջջային զեկուցվող հաղորդագրությունները"</string>
     <string name="permdesc_readCellBroadcasts" msgid="6361972776080458979">"Թույլ է տալիս հավելվածին կարդալ ձեր սարքի կողմից ստացված բջջային հեռարձակվող հաղորդագրությունները: Բջջային հեռարձակվող զգուշացումները ուղարկվում են որոշ վայրերում` արտակարգ իրավիճակների մասին ձեզ զգուշացնելու համար: Վնասարար հավելվածները կարող են խանգարել ձեր սարքի արդյունավետությանը կամ շահագործմանը, երբ ստացվում է արտակարգ իրավիճակի մասին բջջային հաղորդում:"</string>
     <string name="permlab_subscribedFeedsRead" msgid="4756609637053353318">"կարդալ բաժանորդագրված հոսքերը"</string>
diff --git a/core/res/res/values-in/strings.xml b/core/res/res/values-in/strings.xml
index 4d0eea0..88e396c 100644
--- a/core/res/res/values-in/strings.xml
+++ b/core/res/res/values-in/strings.xml
@@ -344,6 +344,10 @@
     <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_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>
diff --git a/core/res/res/values-is/strings.xml b/core/res/res/values-is/strings.xml
index 558f4af..32461d3 100644
--- a/core/res/res/values-is/strings.xml
+++ b/core/res/res/values-is/strings.xml
@@ -344,6 +344,10 @@
     <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_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>
diff --git a/core/res/res/values-it/strings.xml b/core/res/res/values-it/strings.xml
index d0cded8..6e25563 100644
--- a/core/res/res/values-it/strings.xml
+++ b/core/res/res/values-it/strings.xml
@@ -283,7 +283,7 @@
     <string name="permgrouprequest_contacts" msgid="6032805601881764300">"Consentire all\'app &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; di accedere ai tuoi contatti?"</string>
     <string name="permgrouplab_location" msgid="7275582855722310164">"Geolocalizz."</string>
     <string name="permgroupdesc_location" msgid="1346617465127855033">"accedere alla posizione di questo dispositivo"</string>
-    <string name="permgrouprequest_location" msgid="3788275734953323491">"Consentire all\'app &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; di accedere alla posizione di questo dispositivo?"</string>
+    <string name="permgrouprequest_location" msgid="3788275734953323491">"Consentire all\'app &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; di accedere alla posizione del dispositivo?"</string>
     <string name="permgrouprequestdetail_location" msgid="1347189607421252902">"L\'app avrà accesso alla posizione soltanto quando la usi"</string>
     <string name="permgroupbackgroundrequest_location" msgid="5039063878675613235">"Consentire a &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; di accedere &lt;b&gt;sempre&lt;/b&gt; alla posizione di questo dispositivo?"</string>
     <string name="permgroupbackgroundrequestdetail_location" msgid="4597006851453417387">"L\'app al momento può accedere alla posizione soltanto mentre la usi"</string>
@@ -324,8 +324,8 @@
     <string name="capability_desc_canControlMagnification" msgid="4791858203568383773">"Controlla il livello di zoom e la posizione del display."</string>
     <string name="capability_title_canPerformGestures" msgid="7418984730362576862">"Eseguire gesti"</string>
     <string name="capability_desc_canPerformGestures" msgid="8296373021636981249">"Consente di toccare, far scorrere, pizzicare ed eseguire altri gesti."</string>
-    <string name="capability_title_canCaptureFingerprintGestures" msgid="6309568287512278670">"Gesti con sensore di impronte digitali"</string>
-    <string name="capability_desc_canCaptureFingerprintGestures" msgid="4386487962402228670">"È in grado di rilevare i gesti compiuti con il sensore di impronte digitali dei dispositivi."</string>
+    <string name="capability_title_canCaptureFingerprintGestures" msgid="6309568287512278670">"Gesti con sensore di impronte"</string>
+    <string name="capability_desc_canCaptureFingerprintGestures" msgid="4386487962402228670">"È in grado di rilevare i gesti compiuti con il sensore di impronte dei dispositivi."</string>
     <string name="permlab_statusBar" msgid="7417192629601890791">"disattivazione o modifica della barra di stato"</string>
     <string name="permdesc_statusBar" msgid="8434669549504290975">"Consente all\'applicazione di disattivare la barra di stato o di aggiungere e rimuovere icone di sistema."</string>
     <string name="permlab_statusBarService" msgid="4826835508226139688">"ruolo di barra di stato"</string>
@@ -344,6 +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_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="permlab_subscribedFeedsRead" msgid="4756609637053353318">"lettura feed sottoscritti"</string>
@@ -512,10 +516,10 @@
     <string name="permdesc_requestPasswordComplexity" msgid="4730994229754212347">"Consente all\'app di conoscere il livello di complessità del blocco schermo (alto, medio, basso o nessuno), che indica l\'intervallo di caratteri possibile e il tipo di blocco schermo. L\'app può inoltre suggerire agli utenti di aggiornare il blocco schermo a un livello specifico di complessità, ma gli utenti possono ignorare liberamente il suggerimento e uscire. Tieni presente che il blocco schermo non viene memorizzato come testo non crittografato, quindi l\'app non conosce la password esatta."</string>
     <string name="permlab_useBiometric" msgid="8837753668509919318">"utilizzo di hardware biometrico"</string>
     <string name="permdesc_useBiometric" msgid="8389855232721612926">"Consente all\'app di utilizzare hardware biometrico per eseguire l\'autenticazione"</string>
-    <string name="permlab_manageFingerprint" msgid="5640858826254575638">"gestione di hardware per il riconoscimento delle impronte digitali"</string>
-    <string name="permdesc_manageFingerprint" msgid="178208705828055464">"Consente all\'app di richiamare metodi per aggiungere e rimuovere modelli di impronte digitali da utilizzare."</string>
-    <string name="permlab_useFingerprint" msgid="3150478619915124905">"utilizzo di hardware per il riconoscimento delle impronte digitali"</string>
-    <string name="permdesc_useFingerprint" msgid="9165097460730684114">"Consente all\'app di utilizzare l\'hardware per il riconoscimento delle impronte digitali per eseguire l\'autenticazione"</string>
+    <string name="permlab_manageFingerprint" msgid="5640858826254575638">"gestione di hardware per il riconoscimento delle impronte"</string>
+    <string name="permdesc_manageFingerprint" msgid="178208705828055464">"Consente all\'app di richiamare metodi per aggiungere e rimuovere modelli di impronte da utilizzare."</string>
+    <string name="permlab_useFingerprint" msgid="3150478619915124905">"utilizzo di hardware per il riconoscimento delle impronte"</string>
+    <string name="permdesc_useFingerprint" msgid="9165097460730684114">"Consente all\'app di utilizzare l\'hardware per il riconoscimento delle impronte per eseguire l\'autenticazione"</string>
     <string name="permlab_audioWrite" msgid="2661772059799779292">"modifica della tua raccolta musicale"</string>
     <string name="permdesc_audioWrite" msgid="8888544708166230494">"Consente all\'app di modificare la tua raccolta musicale."</string>
     <string name="permlab_videoWrite" msgid="128769316366746446">"modifica della tua raccolta di video"</string>
@@ -530,30 +534,30 @@
     <string name="biometric_not_recognized" msgid="5770511773560736082">"Non riconosciuto"</string>
     <string name="biometric_error_canceled" msgid="349665227864885880">"Autenticazione annullata"</string>
     <string name="biometric_error_device_not_secured" msgid="6583143098363528349">"Non hai impostato PIN, sequenza o password"</string>
-    <string name="fingerprint_acquired_partial" msgid="735082772341716043">"Rilevata impronta digitale parziale. Riprova."</string>
-    <string name="fingerprint_acquired_insufficient" msgid="4596546021310923214">"Impossibile elaborare l\'impronta digitale. Riprova."</string>
-    <string name="fingerprint_acquired_imager_dirty" msgid="1087209702421076105">"Il sensore di impronte digitali è sporco. Puliscilo e riprova."</string>
+    <string name="fingerprint_acquired_partial" msgid="735082772341716043">"Rilevata impronta parziale. Riprova."</string>
+    <string name="fingerprint_acquired_insufficient" msgid="4596546021310923214">"Impossibile elaborare l\'impronta. Riprova."</string>
+    <string name="fingerprint_acquired_imager_dirty" msgid="1087209702421076105">"Il sensore di impronte è sporco. Puliscilo e riprova."</string>
     <string name="fingerprint_acquired_too_fast" msgid="6470642383109155969">"Movimento del dito troppo rapido. Riprova."</string>
     <string name="fingerprint_acquired_too_slow" msgid="59250885689661653">"Movimento del dito troppo lento. Riprova."</string>
   <string-array name="fingerprint_acquired_vendor">
   </string-array>
-    <string name="fingerprint_authenticated" msgid="5309333983002526448">"Impronta digitale autenticata"</string>
+    <string name="fingerprint_authenticated" msgid="5309333983002526448">"Impronta autenticata"</string>
     <string name="face_authenticated_no_confirmation_required" msgid="4018680978348659031">"Volto autenticato"</string>
     <string name="face_authenticated_confirmation_required" msgid="8778347003507633610">"Volto autenticato, premi Conferma"</string>
-    <string name="fingerprint_error_hw_not_available" msgid="7955921658939936596">"Hardware per l\'impronta digitale non disponibile."</string>
-    <string name="fingerprint_error_no_space" msgid="1055819001126053318">"Impossibile memorizzare l\'impronta digitale. Rimuovi un\'impronta esistente."</string>
-    <string name="fingerprint_error_timeout" msgid="3927186043737732875">"Timeout impronta digitale. Riprova."</string>
-    <string name="fingerprint_error_canceled" msgid="4402024612660774395">"Operazione associata all\'impronta digitale annullata."</string>
-    <string name="fingerprint_error_user_canceled" msgid="7999639584615291494">"Operazione di autenticazione dell\'impronta digitale annullata dall\'utente."</string>
+    <string name="fingerprint_error_hw_not_available" msgid="7955921658939936596">"Hardware per l\'impronta non disponibile."</string>
+    <string name="fingerprint_error_no_space" msgid="1055819001126053318">"Impossibile memorizzare l\'impronta. Rimuovi un\'impronta esistente."</string>
+    <string name="fingerprint_error_timeout" msgid="3927186043737732875">"Timeout impronta. Riprova."</string>
+    <string name="fingerprint_error_canceled" msgid="4402024612660774395">"Operazione associata all\'impronta annullata."</string>
+    <string name="fingerprint_error_user_canceled" msgid="7999639584615291494">"Operazione di autenticazione dell\'impronta annullata dall\'utente."</string>
     <string name="fingerprint_error_lockout" msgid="5536934748136933450">"Troppi tentativi. Riprova più tardi."</string>
-    <string name="fingerprint_error_lockout_permanent" msgid="5033251797919508137">"Troppi tentativi. Sensore di impronte digitali disattivato."</string>
+    <string name="fingerprint_error_lockout_permanent" msgid="5033251797919508137">"Troppi tentativi. Sensore di impronte disattivato."</string>
     <string name="fingerprint_error_unable_to_process" msgid="6107816084103552441">"Riprova."</string>
     <string name="fingerprint_error_no_fingerprints" msgid="7654382120628334248">"Nessuna impronta digitale registrata."</string>
-    <string name="fingerprint_error_hw_not_present" msgid="409523969613176352">"Questo dispositivo non dispone di sensore di impronte digitali."</string>
+    <string name="fingerprint_error_hw_not_present" msgid="409523969613176352">"Questo dispositivo non dispone di sensore di impronte."</string>
     <string name="fingerprint_name_template" msgid="5870957565512716938">"Dito <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 dell\'impronta digitale"</string>
+    <string name="fingerprint_icon_content_description" msgid="2340202869968465936">"Icona dell\'impronta"</string>
     <string name="permlab_manageFace" msgid="7262837876352591553">"gestione dell\'hardware per Sblocco col sorriso"</string>
     <string name="permdesc_manageFace" msgid="8919637120670185330">"Consente all\'app di richiamare i metodi per aggiungere e rimuovere i modelli di volti."</string>
     <string name="permlab_useFaceAuthentication" msgid="2565716575739037572">"utilizzo dell\'hardware per Sblocco col sorriso"</string>
@@ -1583,8 +1587,8 @@
     <string name="expires_on" msgid="3676242949915959821">"Scade il:"</string>
     <string name="serial_number" msgid="758814067660862493">"Numero di serie:"</string>
     <string name="fingerprints" msgid="4516019619850763049">"Fingerprint:"</string>
-    <string name="sha256_fingerprint" msgid="4391271286477279263">"Fingerprint SHA-256:"</string>
-    <string name="sha1_fingerprint" msgid="7930330235269404581">"Fingerprint SHA-1:"</string>
+    <string name="sha256_fingerprint" msgid="4391271286477279263">"Impronta SHA-256:"</string>
+    <string name="sha1_fingerprint" msgid="7930330235269404581">"Impronta 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 8b2b625..6e61213 100644
--- a/core/res/res/values-iw/strings.xml
+++ b/core/res/res/values-iw/strings.xml
@@ -350,6 +350,10 @@
     <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_readCellBroadcasts" msgid="1598328843619646166">"קריאת הודעות שידור סלולרי"</string>
     <string name="permdesc_readCellBroadcasts" msgid="6361972776080458979">"מאפשר לאפליקציה לקרוא הודעות שידור סלולרי שהתקבלו במכשיר שלך. התראות שידור סלולרי נשלחות במקומות מסוימים על מנת להזהיר אותך מפני מצבי חירום. אפליקציות זדוניות עשויות להפריע לביצועים או לפעולה של המכשיר שלך כאשר מתקבל שידור חירום סלולרי."</string>
     <string name="permlab_subscribedFeedsRead" msgid="4756609637053353318">"קרא עדכוני מנויים"</string>
diff --git a/core/res/res/values-ja/strings.xml b/core/res/res/values-ja/strings.xml
index 39f05db..15e10e4 100644
--- a/core/res/res/values-ja/strings.xml
+++ b/core/res/res/values-ja/strings.xml
@@ -344,6 +344,10 @@
     <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_readCellBroadcasts" msgid="1598328843619646166">"緊急速報メール SMS の読み取り"</string>
     <string name="permdesc_readCellBroadcasts" msgid="6361972776080458979">"デバイスで受信した緊急速報メール SMS の読み取りをアプリに許可します。緊急速報メールは、緊急事態を警告する目的で一部の地域に配信されます。緊急速報メールの受信時に、悪意のあるアプリによってデバイスの動作や処理が妨害される恐れがあります。"</string>
     <string name="permlab_subscribedFeedsRead" msgid="4756609637053353318">"登録したフィードの読み取り"</string>
diff --git a/core/res/res/values-ka/strings.xml b/core/res/res/values-ka/strings.xml
index 2f216f9..a66d897 100644
--- a/core/res/res/values-ka/strings.xml
+++ b/core/res/res/values-ka/strings.xml
@@ -344,6 +344,10 @@
     <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_readCellBroadcasts" msgid="1598328843619646166">"მასიური დაგზავნის შეტყობინებების წაკითხვა"</string>
     <string name="permdesc_readCellBroadcasts" msgid="6361972776080458979">"აპს შეეძლება, წაიკითხოს თქვენს მოწყობილობაზე გამოგზავნილი ქსელის სამაუწყებლო შეტყობინებები. სამაუწყებლო გაფრთხილებები მოგეწოდებათ ზოგიერთ ადგილზე ექსტრემალური სიტუაციების შესახებ გასაფრთხილებლად. ქსელის გადაუდებელი შეტყონიბენის მიღების დროს მავნე აპებმა შეიძლება ხელი შეუშალონ თქვენი მოწყობილობის ფუნქციონირებას ან ოპერაციებს."</string>
     <string name="permlab_subscribedFeedsRead" msgid="4756609637053353318">"გამოწერილი არხების წაკითხვა"</string>
diff --git a/core/res/res/values-kk/strings.xml b/core/res/res/values-kk/strings.xml
index 8fb6eb7..af6b788 100644
--- a/core/res/res/values-kk/strings.xml
+++ b/core/res/res/values-kk/strings.xml
@@ -344,6 +344,10 @@
     <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_readCellBroadcasts" msgid="1598328843619646166">"ұялы хабар тарату хабарларын оқу"</string>
     <string name="permdesc_readCellBroadcasts" msgid="6361972776080458979">"Қолданбаға ұялы таратылым хабарларын оқу мүмкіндігін береді. Ұялы таратылым дабылдары кейбір аймақтарда төтенше жағдай туралы ескерту үшін қолданылады. Төтенше ұялы хабарлар келгенде залалды қолданбалар құрылғының жұмысына кедергі жасауы мүмкін."</string>
     <string name="permlab_subscribedFeedsRead" msgid="4756609637053353318">"жазылған ағындарды оқу"</string>
diff --git a/core/res/res/values-km/strings.xml b/core/res/res/values-km/strings.xml
index 6355289..cf9b9d2 100644
--- a/core/res/res/values-km/strings.xml
+++ b/core/res/res/values-km/strings.xml
@@ -344,6 +344,10 @@
     <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_readCellBroadcasts" msgid="1598328843619646166">"អាន​សារ​ប្រកាស​ចល័ត"</string>
     <string name="permdesc_readCellBroadcasts" msgid="6361972776080458979">"ឲ្យ​កម្មវិធី​អាន​សារ​ប្រកាស​ការ​ហៅ​ដែល​ឧបករណ៍​របស់​​អ្នក​បាន​ទទួល។ ការ​ជូន​ដំណឹង​ប្រកាស​ចល័ត​ត្រូវ​បាន​បញ្ជូន​ទៅ​ទីតាំង​មួយ​ចំនួន ដើម្បី​ព្រមាន​អ្នក​អំពី​ស្ថានភាព​អាសន្ន។ កម្មវិធី​ព្យាបាទ​អាច​ជ្រៀតជ្រែក​ការ​អនុវត្ត ឬ​ប្រតិបត្តិការ​ឧបករណ៍​របស់​អ្នក​​ពេល​ទទួល​ការ​ប្រកាស​ចល័ត​ពេល​អាសន្ន។"</string>
     <string name="permlab_subscribedFeedsRead" msgid="4756609637053353318">"អាន​អត្ថបទ​ព័ត៌មាន​បាន​ជាវ"</string>
@@ -1585,8 +1589,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-kn/strings.xml b/core/res/res/values-kn/strings.xml
index 7802129..028d563 100644
--- a/core/res/res/values-kn/strings.xml
+++ b/core/res/res/values-kn/strings.xml
@@ -344,6 +344,10 @@
     <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_readCellBroadcasts" msgid="1598328843619646166">"ಸೆಲ್ ಪ್ರಸಾರದ ಸಂದೇಶಗಳನ್ನು ಓದಿರಿ"</string>
     <string name="permdesc_readCellBroadcasts" msgid="6361972776080458979">"ನಿಮ್ಮ ಸಾಧನದಿಂದ ಸ್ವೀಕರಿಸಿದ ಸೆಲ್ ಪ್ರಸಾರ ಸಂದೇಶಗಳನ್ನು ರೀಡ್ ಮಾಡಲು ಅಪ್ಲಿಕೇಶನ್‌‌ಗೆ ಅನುಮತಿಸುತ್ತದೆ. ಸೆಲ್ ಪ್ರಸಾರ ಎಚ್ಚರಿಕೆಗಳನ್ನು ತುರ್ತು ಸಂದರ್ಭಗಳಲ್ಲಿ ನಿಮಗೆ ಎಚ್ಚರಿಸುವ ಸಲುವಾಗಿ ಕೆಲವು ಸ್ಥಳಗಳಲ್ಲಿ ವಿತರಿಸಲಾಗುತ್ತದೆ. ದುರುದ್ದೇಶಪೂರಿತ ಅಪ್ಲಿಕೇಶನ್‌‌‌ಗಳು ತುರ್ತು ಸೆಲ್ ಪ್ರಸಾರವನ್ನು ಸ್ವೀಕರಿಸುವಾಗ, ನಿಮ್ಮ ಸಾಧನದ ಕಾರ್ಯಕ್ಷಮತೆ ಇಲ್ಲವೇ ಕಾರ್ಯಾಚರಣೆಯಲ್ಲಿ ಹಸ್ತಕ್ಷೇಪ ಮಾಡಬಹುದು."</string>
     <string name="permlab_subscribedFeedsRead" msgid="4756609637053353318">"ಚಂದಾದಾರ ಫೀಡ್‌ಗಳನ್ನು ಓದಿ"</string>
diff --git a/core/res/res/values-ko/strings.xml b/core/res/res/values-ko/strings.xml
index 72302c3..f81cc00 100644
--- a/core/res/res/values-ko/strings.xml
+++ b/core/res/res/values-ko/strings.xml
@@ -344,6 +344,10 @@
     <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_readCellBroadcasts" msgid="1598328843619646166">"셀 브로드캐스트 메시지 읽기"</string>
     <string name="permdesc_readCellBroadcasts" msgid="6361972776080458979">"앱이 기기가 수신한 셀 브로드캐스트 메시지를 읽을 수 있도록 합니다. 비상 상황임을 알리기 위해 일부 지역에서 셀 브로드캐스트 경고가 전달됩니다. 비상 셀 브로드캐스트를 수신할 때 악성 앱이 기기의 성능이나 작동을 방해할 수 있습니다."</string>
     <string name="permlab_subscribedFeedsRead" msgid="4756609637053353318">"가입된 피드 읽기"</string>
diff --git a/core/res/res/values-ky/strings.xml b/core/res/res/values-ky/strings.xml
index 09ee99c..c61992c 100644
--- a/core/res/res/values-ky/strings.xml
+++ b/core/res/res/values-ky/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>
@@ -344,6 +344,10 @@
     <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_readCellBroadcasts" msgid="1598328843619646166">"уюктук берүү билдирүүлөрүн окуу"</string>
     <string name="permdesc_readCellBroadcasts" msgid="6361972776080458979">"Колдонмого түзмөгүңүз кабыл алган уюк берүүнүн билдирүүлөрүн окууга жол берет. Шашылыш эскертүү билдирүүлөрү кээ бир жерлердеги өзгөчө кырдаалдар тууралу сизди эскертүү үчүн жөнөтүлөт. Зыяндуу колдономолор шашылыш эскертүүлөр берилип жатканда, сиздин түзмөктүн иштешине жолтоо болушу мүмкүн."</string>
     <string name="permlab_subscribedFeedsRead" msgid="4756609637053353318">"жазылган түрмөктөрдү окуу"</string>
@@ -1077,7 +1081,7 @@
     <string name="Midnight" msgid="5630806906897892201">"Түн ортосу"</string>
     <string name="elapsed_time_short_format_mm_ss" msgid="4431555943828711473">"<xliff:g id="MINUTES">%1$02d</xliff:g>:<xliff:g id="SECONDS">%2$02d</xliff:g>"</string>
     <string name="elapsed_time_short_format_h_mm_ss" msgid="1846071997616654124">"<xliff:g id="HOURS">%1$d</xliff:g>:<xliff:g id="MINUTES">%2$02d</xliff:g>:<xliff:g id="SECONDS">%3$02d</xliff:g>"</string>
-    <string name="selectAll" msgid="6876518925844129331">"Бардыгын тандоо"</string>
+    <string name="selectAll" msgid="6876518925844129331">"Баарын тандоо"</string>
     <string name="cut" msgid="3092569408438626261">"Кесүү"</string>
     <string name="copy" msgid="2681946229533511987">"Көчүрүү"</string>
     <string name="failed_to_copy_to_clipboard" msgid="1833662432489814471">"Алмашуу буферине көчүрүлбөй калды"</string>
@@ -1317,7 +1321,7 @@
     <string name="sms_control_title" msgid="7296612781128917719">"SMS билдирүүлөр жөнөтүлүүдө"</string>
     <string name="sms_control_message" msgid="3867899169651496433">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; көп SMS билдирүүлөрдү жөнөтүп жатат. Бул колдонмо билдирүүлөрдү жөнөтө берсинби?"</string>
     <string name="sms_control_yes" msgid="3663725993855816807">"Ооба"</string>
-    <string name="sms_control_no" msgid="625438561395534982">"Жок"</string>
+    <string name="sms_control_no" msgid="625438561395534982">"Тыюу салынат"</string>
     <string name="sms_short_code_confirm_message" msgid="1645436466285310855">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; &lt;b&gt;<xliff:g id="DEST_ADDRESS">%2$s</xliff:g>&lt;/b&gt; номуруна билдирүү жөнөткөнү жатат."</string>
     <string name="sms_short_code_details" msgid="5873295990846059400">"Бул уюлдук эсебиңиздеги төлөмдөргө "<b>"алып келиши мүмкүн"</b>"."</string>
     <string name="sms_premium_short_code_details" msgid="7869234868023975"><b>"Бул уюлдук эсебиңиздеги төлөмдөргө алып келет."</b></string>
@@ -1359,8 +1363,8 @@
     <string name="usb_power_notification_message" msgid="4647527153291917218">"Туташкан түзмөк кубатталууда. Дагы параметрлерди көрүү үчүн таптап коюңуз."</string>
     <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_title" msgid="6729044778949189918">"Мүчүлүштүктөрдү USB аркылуу оңдоо иштеп жатат"</string>
+    <string name="adb_active_notification_message" msgid="7463062450474107752">"Өчүрүү үчүн тийип коюңуз"</string>
     <!-- no translation found for adb_active_notification_message (8470296818270110396) -->
     <skip />
     <string name="test_harness_mode_notification_title" msgid="2216359742631914387">"Сыноо программасынын режими иштетилди"</string>
@@ -1455,7 +1459,7 @@
     <string name="grant_credentials_permission_message_footer" msgid="3125211343379376561">"Бул өтүнүчкө уруксат бересизби?"</string>
     <string name="grant_permissions_header_text" msgid="6874497408201826708">"Жетки талабы"</string>
     <string name="allow" msgid="7225948811296386551">"Уруксат берүү"</string>
-    <string name="deny" msgid="2081879885755434506">"Жок"</string>
+    <string name="deny" msgid="2081879885755434506">"Уруксат берилбейт"</string>
     <string name="permission_request_notification_title" msgid="6486759795926237907">"Уруксат талап кылуу"</string>
     <string name="permission_request_notification_with_subtitle" msgid="8530393139639560189">"Кийинки эсепке\nуруксат талап кылынууда: <xliff:g id="ACCOUNT">%s</xliff:g>."</string>
     <string name="forward_intent_to_owner" msgid="1207197447013960896">"Бул колдонмо жумуш профилиңиздин сыртында колдонулуп жатат"</string>
diff --git a/core/res/res/values-lo/strings.xml b/core/res/res/values-lo/strings.xml
index 00bfc0e..fb3afb3 100644
--- a/core/res/res/values-lo/strings.xml
+++ b/core/res/res/values-lo/strings.xml
@@ -344,6 +344,10 @@
     <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_readCellBroadcasts" msgid="1598328843619646166">"ອ່ານຂໍ້ຄວາມກະຈາຍສັນຍານຂອງເສົາສັນຍານ"</string>
     <string name="permdesc_readCellBroadcasts" msgid="6361972776080458979">"ອະນຸຍາດໃຫ້ແອັບຯ ສາມາດອ່ານຂໍ້ຄວາມແຈ້ງເຕືອນເຫດສຸກເສີນ ທີ່ໄດ້ຮັບໂດຍອຸປະກອນຂອງທ່ານ. ການແຈ້ງເຕືອນສຸກເສີນທີ່ມີໃຫ້ບໍລິການໃນບາງພື້ນທີ່ ເພື່ອແຈ້ງເຕືອນໃຫ້ທ່ານຮູ້ເຖິງສະຖານະການສຸກເສີນ. ແອັບພລິເຄຊັນທີ່ເປັນອັນຕະລາຍອາດລົບກວນປະສິດທິພາບ ຫຼືການດຳເນີນງານຂອງອຸປະກອນຂອງທ່ານ ເມື່ອໄດ້ການຮັບແຈ້ງເຕືອນສຸກເສີນຈາກສະຖານີມືຖື."</string>
     <string name="permlab_subscribedFeedsRead" msgid="4756609637053353318">"ອ່ານຂໍ້ມູນຟີດທີ່ສະໝັກໄວ້"</string>
diff --git a/core/res/res/values-lt/strings.xml b/core/res/res/values-lt/strings.xml
index b615b24..be9e32f 100644
--- a/core/res/res/values-lt/strings.xml
+++ b/core/res/res/values-lt/strings.xml
@@ -350,6 +350,10 @@
     <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_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>
diff --git a/core/res/res/values-lv/strings.xml b/core/res/res/values-lv/strings.xml
index acc1430..89575c6 100644
--- a/core/res/res/values-lv/strings.xml
+++ b/core/res/res/values-lv/strings.xml
@@ -347,6 +347,10 @@
     <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_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>
diff --git a/core/res/res/values-mk/strings.xml b/core/res/res/values-mk/strings.xml
index 761d965..7144e4d 100644
--- a/core/res/res/values-mk/strings.xml
+++ b/core/res/res/values-mk/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>
@@ -344,6 +344,10 @@
     <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_readCellBroadcasts" msgid="1598328843619646166">"прочитај пораки за мобилно емитување"</string>
     <string name="permdesc_readCellBroadcasts" msgid="6361972776080458979">"Овозможува апликациите да ги читаат пораките за мобилно емитување што ги прима вашиот уред. Предупредувањата за мобилно емитување се доставуваат на некои локации, за да ве предупредат на итни ситуации. Злонамерните апликации може да пречат во ефикасноста или работењето на вашиот уред кога се прима емитување за итен случај."</string>
     <string name="permlab_subscribedFeedsRead" msgid="4756609637053353318">"читај претплатени навестувања на содржина"</string>
@@ -656,7 +660,7 @@
     <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="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 7876c29..479bb3a 100644
--- a/core/res/res/values-ml/strings.xml
+++ b/core/res/res/values-ml/strings.xml
@@ -344,6 +344,10 @@
     <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_readCellBroadcasts" msgid="1598328843619646166">"സെൽ പ്രക്ഷേപണ സന്ദേശങ്ങൾ റീഡുചെയ്യുക"</string>
     <string name="permdesc_readCellBroadcasts" msgid="6361972776080458979">"നിങ്ങളുടെ ഉപകരണത്തിൽ ലഭിച്ച സെൽ പ്രക്ഷേപണ സന്ദേശങ്ങൾ റീഡുചെയ്യാൻ അപ്ലിക്കേഷനെ അനുവദിക്കുന്നു. അടിയന്തര സാഹചര്യങ്ങളെക്കുറിച്ച് നിങ്ങൾക്ക് മുന്നറിയിപ്പ് നൽകാനായി ചില ലൊക്കേഷനുകളിൽ നൽകപ്പെടുന്നവയാണ് സെൽ പ്രക്ഷേപണ അലേർട്ടുകൾ. ഒരു അടിയന്തര സെൽ പ്രക്ഷേപണം ലഭിക്കുമ്പോൾ, ക്ഷുദ്രകരമായ അപ്ലിക്കേഷനുകൾ നിങ്ങളുടെ ഉപകരണത്തിന്റെ പ്രകടനമോ പ്രവർത്തനമോ തടസ്സപ്പെടുത്താനിടയുണ്ട്."</string>
     <string name="permlab_subscribedFeedsRead" msgid="4756609637053353318">"സബ്‌സ്ക്രൈബ് ചെയ്‌ത ഫീഡുകൾ വായിക്കുക"</string>
diff --git a/core/res/res/values-mn/strings.xml b/core/res/res/values-mn/strings.xml
index 1a47403..1f29956 100644
--- a/core/res/res/values-mn/strings.xml
+++ b/core/res/res/values-mn/strings.xml
@@ -344,6 +344,10 @@
     <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_readCellBroadcasts" msgid="1598328843619646166">"үүрэн өргөн дамжууллын мессеж унших"</string>
     <string name="permdesc_readCellBroadcasts" msgid="6361972776080458979">"Апп нь таны төхөөрөмжийн хүлээн авсан үүрэн өргөн дамжуулах мессежийг унших боломжтой. Үүрэн өргөн дамжууллын мэдэгдэл нь яаралтай нөхцөл байдлыг анхааруулах зорилгоор зарим байршлуудад хүрдэг. Хортой апп нь яаралтай үүрэн өргөн дамжууллыг хүлээн авсан үед таны төхөөрөмжийн ажиллагаа болон чадамжид нөлөөлөх боломжтой."</string>
     <string name="permlab_subscribedFeedsRead" msgid="4756609637053353318">"бүртгүүлсэн хангамжийг унших"</string>
diff --git a/core/res/res/values-mr/strings.xml b/core/res/res/values-mr/strings.xml
index 05638df..5c6e358 100644
--- a/core/res/res/values-mr/strings.xml
+++ b/core/res/res/values-mr/strings.xml
@@ -344,6 +344,10 @@
     <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_readCellBroadcasts" msgid="1598328843619646166">"सेल प्रसारण मेसेज वाचा"</string>
     <string name="permdesc_readCellBroadcasts" msgid="6361972776080458979">"आपल्या डिव्हाइसद्वारे प्राप्त केलेले सेल प्रसारण मेसेज वाचण्यासाठी अ‍ॅप ला अनुमती देते. काही स्थानांमध्ये तुम्हाला आणीबाणीच्या परिस्थितीची चेतावणी देण्यासाठी सेल प्रसारण सूचना वितरीत केल्या जातात. आणीबाणी सेल प्रसारण प्राप्त होते तेव्हा आपल्या डिव्हाइसच्या कार्यप्रदर्शनात किंवा कार्यात दुर्भावनापूर्ण अ‍ॅप्स व्यत्यय आणू शकतात."</string>
     <string name="permlab_subscribedFeedsRead" msgid="4756609637053353318">"सदस्यता घेतलेली फीड वाचा"</string>
@@ -1001,7 +1005,7 @@
     <string name="weeks" msgid="6509623834583944518">"आठवडे"</string>
     <string name="year" msgid="4001118221013892076">"वर्ष"</string>
     <string name="years" msgid="6881577717993213522">"वर्षे"</string>
-    <string name="now_string_shortest" msgid="8912796667087856402">"आत्ता"</string>
+    <string name="now_string_shortest" msgid="8912796667087856402">"आता"</string>
     <plurals name="duration_minutes_shortest" formatted="false" msgid="3957499975064245495">
       <item quantity="other"><xliff:g id="COUNT_1">%d</xliff:g>मि</item>
       <item quantity="one"><xliff:g id="COUNT_0">%d</xliff:g>मि</item>
diff --git a/core/res/res/values-ms/strings.xml b/core/res/res/values-ms/strings.xml
index d5c5475..a7a4c99 100644
--- a/core/res/res/values-ms/strings.xml
+++ b/core/res/res/values-ms/strings.xml
@@ -344,6 +344,10 @@
     <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_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>
diff --git a/core/res/res/values-my/strings.xml b/core/res/res/values-my/strings.xml
index 5506166..cbe8af4 100644
--- a/core/res/res/values-my/strings.xml
+++ b/core/res/res/values-my/strings.xml
@@ -344,6 +344,10 @@
     <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_readCellBroadcasts" msgid="1598328843619646166">"စာတိုများ ဖြန့်ဝေခြင်းစနစ်အား ဖတ်ခြင်း"</string>
     <string name="permdesc_readCellBroadcasts" msgid="6361972776080458979">"အပလီကေးရှင်းကို သင်၏ စက်ပစ္စည်းမှ လက်ခံရရှိသော အများလွှင့်ထုတ်ချက်များကို ဖတ်ရန် ခွင့်ပြုသည်။  အများလွှင့်ထုတ်ချက်များသည် အရေးပေါ်အခြေအနေများကို သင့်အား သတိပေးရန် အချို့ နေရာများတွင် ပို့ပေးသည်။ အရေးပေါ်သတိပေးချက် ထုတ်လွှင့်ချက်ကို လက်ခံရရှိချိန်တွင်အန္တရာယ် ဖြစ်စေနိုင်သော အပလီကေးရှင်းများသည် သင့်စက်ပစ္စည်း၏ လုပ်ငန်းလည်ပတ်မှုနှင့် စွမ်းဆောင်မှုကို ဝင်စွက်ဖက်နိုင်သည်။"</string>
     <string name="permlab_subscribedFeedsRead" msgid="4756609637053353318">"အမည်သွင်းထားသောဖိဖ့်များကို ဖတ်ခြင်း"</string>
@@ -1453,8 +1457,8 @@
     <string name="grant_credentials_permission_message_header" msgid="2106103817937859662">"အောက်ပါထဲက အက်ပ်တစ်ခု သို့မဟုတ် ပိုလျက် သင်၏ အကောင့်ကို၊ ယခု နှင့် အနာဂတ်မှာ ရယူအသုံးချရန် ခွင့်ပြုချက်ကို တောင်းထားသည်။"</string>
     <string name="grant_credentials_permission_message_footer" msgid="3125211343379376561">"ဤတောင်းခံမှုအားခွင့်ပြုမည်လား"</string>
     <string name="grant_permissions_header_text" msgid="6874497408201826708">"သုံးစွဲခွင့် တောင်းဆိုရန်"</string>
-    <string name="allow" msgid="7225948811296386551">"ခွင့်ပြုသည်"</string>
-    <string name="deny" msgid="2081879885755434506">"ငြင်းပယ်သည်"</string>
+    <string name="allow" msgid="7225948811296386551">"ခွင့်ပြုရန်"</string>
+    <string name="deny" msgid="2081879885755434506">"ငြင်းပယ်ရန်"</string>
     <string name="permission_request_notification_title" msgid="6486759795926237907">"ခွင့်ပြုချက် တောင်းခံထားခြင်း"</string>
     <string name="permission_request_notification_with_subtitle" msgid="8530393139639560189">"အကောင့် <xliff:g id="ACCOUNT">%s</xliff:g> အတွက် \n ခွင့်ပြုချက် တောင်းခံထားပြီး"</string>
     <string name="forward_intent_to_owner" msgid="1207197447013960896">"သင်သည် ဒီအက်ပ်ကို သင့်အလုပ်ပရိုဖိုင် ပြင်ပတွင် အသုံးပြုနေ၏"</string>
diff --git a/core/res/res/values-nb/strings.xml b/core/res/res/values-nb/strings.xml
index f6bbaaa..183e2e2 100644
--- a/core/res/res/values-nb/strings.xml
+++ b/core/res/res/values-nb/strings.xml
@@ -344,6 +344,10 @@
     <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_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>
diff --git a/core/res/res/values-ne/strings.xml b/core/res/res/values-ne/strings.xml
index c560822..4c4e1f0 100644
--- a/core/res/res/values-ne/strings.xml
+++ b/core/res/res/values-ne/strings.xml
@@ -344,6 +344,10 @@
     <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_readCellBroadcasts" msgid="1598328843619646166">"सेल प्रसारित सन्देशहरू पढ्नुहोस्"</string>
     <string name="permdesc_readCellBroadcasts" msgid="6361972776080458979">"तपाईंको उपकरणद्वारा प्राप्त सेल प्रसारण सन्देशहरू अनुप्रयोगलाई पढ्न अनुमति दिन्छ। सेल प्रसारण चेतावनीहरू केही स्थानहरूमा तपाईंलाई आपतकालीन गतिविधिहरूको बारेमा सचेत गराउन गरिएका छन्। खराब अनुप्रयोगहरूले एउटा आपतकालीन सेल प्रसारण प्राप्त गर्दछ जब तपाईंको उपकरणको प्रदर्शन वा अपरेशनको साथ हस्तक्षेप गर्न सक्दछन्।"</string>
     <string name="permlab_subscribedFeedsRead" msgid="4756609637053353318">"सदस्य बनाइका फिडहरू पढ्नुहोस्"</string>
diff --git a/core/res/res/values-nl/strings.xml b/core/res/res/values-nl/strings.xml
index 6dc5a64..b3cc884 100644
--- a/core/res/res/values-nl/strings.xml
+++ b/core/res/res/values-nl/strings.xml
@@ -344,6 +344,10 @@
     <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_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>
diff --git a/core/res/res/values-or/strings.xml b/core/res/res/values-or/strings.xml
index bc3c400..eb8f4c6 100644
--- a/core/res/res/values-or/strings.xml
+++ b/core/res/res/values-or/strings.xml
@@ -344,6 +344,10 @@
     <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_readCellBroadcasts" msgid="1598328843619646166">"ସେଲ୍‍ ବ୍ରଡ୍‍କାଷ୍ଟ ମେସେଜ୍‍ ପଢ଼ନ୍ତୁ"</string>
     <string name="permdesc_readCellBroadcasts" msgid="6361972776080458979">"ଆପଣଙ୍କ ଡିଭାଇସ୍‍ରେ ପ୍ରାପ୍ତ ହୋଇଥିବା ସେଲ୍‍ ବ୍ରଡ୍‍କାଷ୍ଟ ମେସେଜ୍‍ ପଢିବାକୁ ଆପ୍‍କୁ ଅନୁମତି ଦିଏ। ଜରୁରୀକାଳୀନ ଅବସ୍ଥା ବିଷୟରେ ଆପଣଙ୍କୁ ସତର୍କ କରାଇବାକୁ କିଛି ଲୋକେଶନ୍‍ରେ ସେଲ୍‍ ବ୍ରଡ୍‍କାଷ୍ଟ ସତର୍କ ଡେଲିଭର୍ କରାଯାଇଥାଏ। ଏକ ଜରୁରୀକାଳୀନ ସେଲ୍‍ ବ୍ରଡ୍‍କାଷ୍ଟ ପ୍ରାପ୍ତ ହେବାପରେ ହାନୀକାରକ ଆପ୍‍ ଆପଣଙ୍କ ଡିଭାଇସ୍‍ର କାର୍ଯ୍ୟକ୍ଷମତା କିମ୍ବା ସଞ୍ଚାଳନାରେ ବାଧା ପହଞ୍ଚାଇପାରନ୍ତି।"</string>
     <string name="permlab_subscribedFeedsRead" msgid="4756609637053353318">"ସବସ୍କ୍ରାଇବ୍ ହୋଇଥିବା ଫୀଡ୍‌କୁ ପଢ଼ନ୍ତୁ"</string>
diff --git a/core/res/res/values-pa/strings.xml b/core/res/res/values-pa/strings.xml
index 74deed1..bc68885 100644
--- a/core/res/res/values-pa/strings.xml
+++ b/core/res/res/values-pa/strings.xml
@@ -344,6 +344,10 @@
     <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_readCellBroadcasts" msgid="1598328843619646166">"ਸੈਲ ਪ੍ਰਸਾਰਨ ਸੁਨੇਹੇ ਪੜ੍ਹੋ"</string>
     <string name="permdesc_readCellBroadcasts" msgid="6361972776080458979">"ਐਪ ਨੂੰ ਤੁਹਾਡੀ ਡੀਵਾਈਸ ਵੱਲੋਂ ਪ੍ਰਾਪਤ ਕੀਤੇ ਸੈੱਲ ਪ੍ਰਸਾਰਣ ਸੁਨੇਹੇ ਪੜ੍ਹਨ ਦੀ ਆਗਿਆ ਦਿੰਦਾ ਹੈ। ਸੈੱਲ ਪ੍ਰਸਾਰਣ ਚਿਤਾਵਨੀਆਂ ਤੁਹਾਨੂੰ ਸੰਕਟਕਾਲੀਨ ਸਥਿਤੀਆਂ ਦੀ ਚਿਤਾਵਨੀ ਦੇਣ ਲਈ ਕੁਝ ਨਿਰਧਾਰਤ ਟਿਕਾਣਿਆਂ ਤੇ ਪ੍ਰਦਾਨ ਕੀਤੀਆਂ ਜਾਂਦੀਆਂ ਹਨ। ਖਰਾਬ ਐਪਾਂ ਤੁਹਾਡੇ ਡੀਵਾਈਸ ਦੇ ਪ੍ਰਦਰਸ਼ਨ ਜਾਂ ਓਪਰੇਸ਼ਨ ਵਿੱਚ ਵਿਘਨ ਪਾ ਸਕਦੀਆਂ ਹਨ ਜਦੋਂ ਇੱਕ ਸੰਕਟਕਾਲੀਨ ਸੈੱਲ ਪ੍ਰਸਾਰਣ ਪ੍ਰਾਪਤ ਕੀਤਾ ਜਾਂਦਾ ਹੈ।"</string>
     <string name="permlab_subscribedFeedsRead" msgid="4756609637053353318">"ਸਬਸਕ੍ਰਾਈਬ ਕੀਤੇ ਫੀਡਸ ਪੜ੍ਹੋ"</string>
diff --git a/core/res/res/values-pl/strings.xml b/core/res/res/values-pl/strings.xml
index b1369c7..1dbe1c1 100644
--- a/core/res/res/values-pl/strings.xml
+++ b/core/res/res/values-pl/strings.xml
@@ -350,6 +350,10 @@
     <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_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>
diff --git a/core/res/res/values-pt-rBR/strings.xml b/core/res/res/values-pt-rBR/strings.xml
index 4dc2700..c5bcb1d 100644
--- a/core/res/res/values-pt-rBR/strings.xml
+++ b/core/res/res/values-pt-rBR/strings.xml
@@ -344,6 +344,10 @@
     <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_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>
diff --git a/core/res/res/values-pt-rPT/strings.xml b/core/res/res/values-pt-rPT/strings.xml
index 141dca3..29ef549 100644
--- a/core/res/res/values-pt-rPT/strings.xml
+++ b/core/res/res/values-pt-rPT/strings.xml
@@ -344,6 +344,10 @@
     <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_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>
diff --git a/core/res/res/values-pt/strings.xml b/core/res/res/values-pt/strings.xml
index 4dc2700..c5bcb1d 100644
--- a/core/res/res/values-pt/strings.xml
+++ b/core/res/res/values-pt/strings.xml
@@ -344,6 +344,10 @@
     <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_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>
diff --git a/core/res/res/values-ro/strings.xml b/core/res/res/values-ro/strings.xml
index 73f31c4..8ee45f9 100644
--- a/core/res/res/values-ro/strings.xml
+++ b/core/res/res/values-ro/strings.xml
@@ -347,6 +347,10 @@
     <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_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>
diff --git a/core/res/res/values-ru/strings.xml b/core/res/res/values-ru/strings.xml
index 9e43592..655cf1b 100644
--- a/core/res/res/values-ru/strings.xml
+++ b/core/res/res/values-ru/strings.xml
@@ -350,6 +350,10 @@
     <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_readCellBroadcasts" msgid="1598328843619646166">"Читать сообщения массовой рассылки"</string>
     <string name="permdesc_readCellBroadcasts" msgid="6361972776080458979">"Приложение получит доступ к сообщениям широковещательных SMS-служб, которые в некоторых странах используются для информирования населения об экстренных ситуациях. Вредоносные программы могут помешать работе устройства, на которое поступают такие сообщения."</string>
     <string name="permlab_subscribedFeedsRead" msgid="4756609637053353318">"Просмотр фидов пользователя"</string>
diff --git a/core/res/res/values-si/strings.xml b/core/res/res/values-si/strings.xml
index cc2a2a89..5fc6b53 100644
--- a/core/res/res/values-si/strings.xml
+++ b/core/res/res/values-si/strings.xml
@@ -344,6 +344,10 @@
     <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_readCellBroadcasts" msgid="1598328843619646166">"සෙල් ප්‍රචාරණ පණිවිඩ කියවීම"</string>
     <string name="permdesc_readCellBroadcasts" msgid="6361972776080458979">"ඔබගේ උපාංගයට ලැබුණු සෙල් විකාශන පණිවිඩ කියවීමට යෙදුමට අවසර දෙන්න. ඔබට හදිසි අවස්ථාවන් පිළිබඳ අනතුරු ඇඟවීමට සෙල් විකාශන පණිවිඩ ඇතැම් ස්ථානවල සිට යවනු ලබයි. හදිසි සෙල් විකාශන ලැබෙන අවස්ථාවකදී, අනිෂ්ට යෙදුම් මඟින් ඔබගේ උපාංගයට කාර්ය සාධනයට හෝ ක්‍රියකරණයට බාධා සිදුවිය හැක."</string>
     <string name="permlab_subscribedFeedsRead" msgid="4756609637053353318">"දායක වූ සංග්‍රහ කියවීම"</string>
diff --git a/core/res/res/values-sk/strings.xml b/core/res/res/values-sk/strings.xml
index 0e49c86..ce17331 100644
--- a/core/res/res/values-sk/strings.xml
+++ b/core/res/res/values-sk/strings.xml
@@ -350,6 +350,10 @@
     <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_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>
diff --git a/core/res/res/values-sl/strings.xml b/core/res/res/values-sl/strings.xml
index 8340046..ec0863f 100644
--- a/core/res/res/values-sl/strings.xml
+++ b/core/res/res/values-sl/strings.xml
@@ -350,6 +350,10 @@
     <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_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>
diff --git a/core/res/res/values-sq/strings.xml b/core/res/res/values-sq/strings.xml
index 411d458..95359cc 100644
--- a/core/res/res/values-sq/strings.xml
+++ b/core/res/res/values-sq/strings.xml
@@ -344,6 +344,10 @@
     <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_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>
@@ -549,7 +553,7 @@
     <string name="fingerprint_error_lockout_permanent" msgid="5033251797919508137">"Shumë përpjekje. Sensori i gjurmës së gishtit u çaktivizua."</string>
     <string name="fingerprint_error_unable_to_process" msgid="6107816084103552441">"Provo përsëri."</string>
     <string name="fingerprint_error_no_fingerprints" msgid="7654382120628334248">"Nuk ka asnjë gjurmë gishti të regjistruar."</string>
-    <string name="fingerprint_error_hw_not_present" msgid="409523969613176352">"Kjo pajisje nuk ka një sensor të gjurmës së gishtit."</string>
+    <string name="fingerprint_error_hw_not_present" msgid="409523969613176352">"Kjo pajisje nuk ka sensor të gjurmës së gishtit."</string>
     <string name="fingerprint_name_template" msgid="5870957565512716938">"Gishti <xliff:g id="FINGERID">%d</xliff:g>"</string>
   <string-array name="fingerprint_error_vendor">
   </string-array>
@@ -1359,7 +1363,7 @@
     <string name="usb_power_notification_message" msgid="4647527153291917218">"Pajisja e lidhur po karikohet. Trokit për opsione të tjera."</string>
     <string name="usb_unsupported_audio_accessory_title" msgid="3529881374464628084">"U zbulua aksesor i audios analoge"</string>
     <string name="usb_unsupported_audio_accessory_message" msgid="6309553946441565215">"Pajisja e bashkuar nuk është e pajtueshme me këtë telefon. Trokit për të mësuar më shumë."</string>
-    <string name="adb_active_notification_title" msgid="6729044778949189918">"Korrigjuesi i USB-së i lidhur"</string>
+    <string name="adb_active_notification_title" msgid="6729044778949189918">"Korrigjuesi i USB-së është i lidhur"</string>
     <string name="adb_active_notification_message" msgid="7463062450474107752">"Trokit për të çaktivizuar korrigjimin e USB-së"</string>
     <string name="adb_active_notification_message" product="tv" msgid="8470296818270110396">"Përzgjidhe për të çaktivizuar korrigjimin e gabimeve të USB-së"</string>
     <string name="test_harness_mode_notification_title" msgid="2216359742631914387">"Modaliteti i lidhjes së testimit është aktivizuar"</string>
@@ -1584,8 +1588,8 @@
     <string name="expires_on" msgid="3676242949915959821">"Skadon më:"</string>
     <string name="serial_number" msgid="758814067660862493">"Numri serik:"</string>
     <string name="fingerprints" msgid="4516019619850763049">"Shenjat e gishtave:"</string>
-    <string name="sha256_fingerprint" msgid="4391271286477279263">"Shenja e gishtit SHA-256:"</string>
-    <string name="sha1_fingerprint" msgid="7930330235269404581">"Shenja e gishtit SHA-1:"</string>
+    <string name="sha256_fingerprint" msgid="4391271286477279263">"Gjurma e gishtit SHA-256:"</string>
+    <string name="sha1_fingerprint" msgid="7930330235269404581">"Gjurma e gishtit SHA-1:"</string>
     <string name="activity_chooser_view_see_all" msgid="4292569383976636200">"Shikoji të gjitha"</string>
     <string name="activity_chooser_view_dialog_title_default" msgid="4710013864974040615">"Zgjidh aktivitetin"</string>
     <string name="share_action_provider_share_with" msgid="5247684435979149216">"Shpërnda publikisht me"</string>
diff --git a/core/res/res/values-sr/strings.xml b/core/res/res/values-sr/strings.xml
index c2d636d..39ad5f4 100644
--- a/core/res/res/values-sr/strings.xml
+++ b/core/res/res/values-sr/strings.xml
@@ -347,6 +347,10 @@
     <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_readCellBroadcasts" msgid="1598328843619646166">"читање порука инфо сервиса"</string>
     <string name="permdesc_readCellBroadcasts" msgid="6361972776080458979">"Омогућава апликацији да чита поруке инфо сервиса које уређај прима. Упозорења инфо сервиса се на неким локацијама примају као упозорења на хитне случајеве. Злонамерне апликације могу да утичу на учинак или ометају функционисање уређаја када се прими порука инфо сервиса о хитном случају."</string>
     <string name="permlab_subscribedFeedsRead" msgid="4756609637053353318">"читање пријављених фидова"</string>
diff --git a/core/res/res/values-sv/strings.xml b/core/res/res/values-sv/strings.xml
index 854e44f..061d7b7 100644
--- a/core/res/res/values-sv/strings.xml
+++ b/core/res/res/values-sv/strings.xml
@@ -344,6 +344,10 @@
     <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_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>
diff --git a/core/res/res/values-sw/strings.xml b/core/res/res/values-sw/strings.xml
index 565cdf9..16df4e3 100644
--- a/core/res/res/values-sw/strings.xml
+++ b/core/res/res/values-sw/strings.xml
@@ -344,6 +344,10 @@
     <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_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>
diff --git a/core/res/res/values-ta/strings.xml b/core/res/res/values-ta/strings.xml
index 9d6d4e1..3b80a43 100644
--- a/core/res/res/values-ta/strings.xml
+++ b/core/res/res/values-ta/strings.xml
@@ -344,6 +344,10 @@
     <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_readCellBroadcasts" msgid="1598328843619646166">"செல் அலைபரப்புச் செய்திகளைப் படித்தல்"</string>
     <string name="permdesc_readCellBroadcasts" msgid="6361972776080458979">"உங்கள் சாதனத்தில் பெறப்படும் செல் அலைபரப்புச் செய்திகளைப் படிப்பதற்குப் ஆப்ஸை அனுமதிக்கிறது. அவசரநிலை சூழ்நிலைகளை உங்களுக்கு எச்சரிக்கைச் செய்வதற்கு சில இடங்களில் செல் அலைபரப்பு விழிப்பூட்டல்கள் வழங்கப்படும். அவசரநிலை மொபைல் அலைபரப்புப் பெறப்படும்போது உங்கள் சாதனத்தின் செயல்திறன் அல்லது செயல்பாட்டுடன் தீங்கிழைக்கும் ஆப்ஸ் அதைத் தடுக்கலாம்."</string>
     <string name="permlab_subscribedFeedsRead" msgid="4756609637053353318">"குழுசேர்ந்த ஊட்டங்களைப் படித்தல்"</string>
diff --git a/core/res/res/values-te/strings.xml b/core/res/res/values-te/strings.xml
index a14bcb9..37e0590 100644
--- a/core/res/res/values-te/strings.xml
+++ b/core/res/res/values-te/strings.xml
@@ -344,6 +344,10 @@
     <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_readCellBroadcasts" msgid="1598328843619646166">"సెల్ ప్రసార సందేశాలను చదవడం"</string>
     <string name="permdesc_readCellBroadcasts" msgid="6361972776080458979">"మీ పరికరం స్వీకరించిన సెల్ ప్రసార సందేశాలను చదవడానికి యాప్‌ను అనుమతిస్తుంది. సెల్ ప్రసార హెచ్చరికలు అత్యవసర పరిస్థితుల గురించి మిమ్మల్ని హెచ్చరించడానికి కొన్ని స్థానాల్లో అందించబడతాయి. అత్యవసర సెల్ ప్రసారం స్వీకరించినప్పుడు హానికరమైన యాప్‌లు మీ పరికరం యొక్క పనితీరు లేదా నిర్వహణకు అంతరాయం కలిగించవచ్చు."</string>
     <string name="permlab_subscribedFeedsRead" msgid="4756609637053353318">"చందా చేయబడిన ఫీడ్‌లను చదవడం"</string>
diff --git a/core/res/res/values-th/strings.xml b/core/res/res/values-th/strings.xml
index 4210354..482288e 100644
--- a/core/res/res/values-th/strings.xml
+++ b/core/res/res/values-th/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>
@@ -344,6 +344,10 @@
     <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_readCellBroadcasts" msgid="1598328843619646166">"อ่านข้อความที่ได้รับจากสถานีมือถือ"</string>
     <string name="permdesc_readCellBroadcasts" msgid="6361972776080458979">"อนุญาตให้แอปอ่านข้อความจากสถานีมือถือที่อุปกรณ์ได้รับ การแจ้งเตือนทางมือถือมีให้บริการในบางพื้นที่ โดยจะแจ้งเตือนคุณเกี่ยวกับสถานการณ์ฉุกเฉิน แอปที่เป็นอันตรายอาจเข้าแทรกแซงการทำงานของอุปกรณ์เมื่อได้รับข้อความแจ้งเตือนฉุกเฉิน"</string>
     <string name="permlab_subscribedFeedsRead" msgid="4756609637053353318">"อ่านฟีดข้อมูลที่สมัครไว้"</string>
diff --git a/core/res/res/values-tl/strings.xml b/core/res/res/values-tl/strings.xml
index 70d2a2f..f2db658 100644
--- a/core/res/res/values-tl/strings.xml
+++ b/core/res/res/values-tl/strings.xml
@@ -344,6 +344,10 @@
     <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_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>
diff --git a/core/res/res/values-tr/strings.xml b/core/res/res/values-tr/strings.xml
index 94e21dc..cf3fbfc 100644
--- a/core/res/res/values-tr/strings.xml
+++ b/core/res/res/values-tr/strings.xml
@@ -344,6 +344,10 @@
     <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_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>
diff --git a/core/res/res/values-uk/strings.xml b/core/res/res/values-uk/strings.xml
index 3c30609..0ac716d 100644
--- a/core/res/res/values-uk/strings.xml
+++ b/core/res/res/values-uk/strings.xml
@@ -350,6 +350,10 @@
     <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_readCellBroadcasts" msgid="1598328843619646166">"читати широкомовні повідомлення мережі"</string>
     <string name="permdesc_readCellBroadcasts" msgid="6361972776080458979">"Дозволяє програмі читати широкомовні повідомлення мережі, отримані пристроєм. Широкомовні сповіщення мережі надсилаються в деяких країнах для попередження про надзвичайні ситуації. Шкідливі програми можуть втручатися у швидкодію чи роботу пристрою під час отримання широкомовного повідомлення мережі про надзвичайну ситуацію."</string>
     <string name="permlab_subscribedFeedsRead" msgid="4756609637053353318">"читати підписані канали"</string>
diff --git a/core/res/res/values-ur/strings.xml b/core/res/res/values-ur/strings.xml
index 59b30f0..43ecaf6 100644
--- a/core/res/res/values-ur/strings.xml
+++ b/core/res/res/values-ur/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,6 +344,10 @@
     <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_readCellBroadcasts" msgid="1598328843619646166">"سیل کے نشریاتی پیغامات پڑھیں"</string>
     <string name="permdesc_readCellBroadcasts" msgid="6361972776080458979">"ایپ کو آپ کے آلے کو موصولہ سیل کے نشریاتی پیغامات پڑھنے کی اجازت دیتا ہے۔ سیل کی نشریاتی الرٹس آپ کو ہنگامی حالات سے مطلع کرنے کیلئے کچھ مقامات میں مہیا کی جاتی ہیں۔ نقصان دہ ایپس کوئی ہنگامی سیل کا نشریہ موصول ہونے پر آپ کے آلے کی کارکردگی یا عمل میں خلل ڈال سکتی ہیں۔"</string>
     <string name="permlab_subscribedFeedsRead" msgid="4756609637053353318">"سبسکرائب کردہ فیڈز پڑھیں"</string>
diff --git a/core/res/res/values-uz/strings.xml b/core/res/res/values-uz/strings.xml
index 22655d0..5ebda207 100644
--- a/core/res/res/values-uz/strings.xml
+++ b/core/res/res/values-uz/strings.xml
@@ -344,6 +344,10 @@
     <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_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>
diff --git a/core/res/res/values-vi/strings.xml b/core/res/res/values-vi/strings.xml
index f36d993..a34585b 100644
--- a/core/res/res/values-vi/strings.xml
+++ b/core/res/res/values-vi/strings.xml
@@ -344,6 +344,10 @@
     <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_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>
@@ -1583,8 +1587,8 @@
     <string name="expires_on" msgid="3676242949915959821">"Hết hạn vào:"</string>
     <string name="serial_number" msgid="758814067660862493">"Số sê-ri:"</string>
     <string name="fingerprints" msgid="4516019619850763049">"Tệp tham chiếu:"</string>
-    <string name="sha256_fingerprint" msgid="4391271286477279263">"Tệp tham chiếu SHA-256:"</string>
-    <string name="sha1_fingerprint" msgid="7930330235269404581">"Tệp tham chiếu SHA-1:"</string>
+    <string name="sha256_fingerprint" msgid="4391271286477279263">"Vân tay SHA-256:"</string>
+    <string name="sha1_fingerprint" msgid="7930330235269404581">"Vân tay SHA-1:"</string>
     <string name="activity_chooser_view_see_all" msgid="4292569383976636200">"Xem tất cả"</string>
     <string name="activity_chooser_view_dialog_title_default" msgid="4710013864974040615">"Chọn hoạt động"</string>
     <string name="share_action_provider_share_with" msgid="5247684435979149216">"Chia sẻ với"</string>
diff --git a/core/res/res/values-zh-rCN/strings.xml b/core/res/res/values-zh-rCN/strings.xml
index 461bbb0..64e0a1b 100644
--- a/core/res/res/values-zh-rCN/strings.xml
+++ b/core/res/res/values-zh-rCN/strings.xml
@@ -344,6 +344,10 @@
     <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_readCellBroadcasts" msgid="1598328843619646166">"读取小区广播消息"</string>
     <string name="permdesc_readCellBroadcasts" msgid="6361972776080458979">"允许应用读取您的设备收到的小区广播消息。小区广播消息是在某些地区发送的、用于发布紧急情况警告的提醒信息。恶意应用可能会在您收到小区紧急广播时干扰您设备的性能或操作。"</string>
     <string name="permlab_subscribedFeedsRead" msgid="4756609637053353318">"读取订阅的供稿"</string>
diff --git a/core/res/res/values-zh-rHK/strings.xml b/core/res/res/values-zh-rHK/strings.xml
index a57b4eb..67a7dbb 100644
--- a/core/res/res/values-zh-rHK/strings.xml
+++ b/core/res/res/values-zh-rHK/strings.xml
@@ -344,6 +344,10 @@
     <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_readCellBroadcasts" msgid="1598328843619646166">"讀取區域廣播訊息"</string>
     <string name="permdesc_readCellBroadcasts" msgid="6361972776080458979">"允許應用程式讀取您裝置接收的區域廣播訊息。某些地點會發出區域廣播警報,警告您發生緊急狀況。惡意應用程式可能會在裝置收到緊急區域廣播時,干擾裝置的性能或運作。"</string>
     <string name="permlab_subscribedFeedsRead" msgid="4756609637053353318">"讀取訂閱的資訊提供"</string>
diff --git a/core/res/res/values-zh-rTW/strings.xml b/core/res/res/values-zh-rTW/strings.xml
index 34fee2b..923a23f 100644
--- a/core/res/res/values-zh-rTW/strings.xml
+++ b/core/res/res/values-zh-rTW/strings.xml
@@ -344,6 +344,10 @@
     <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_readCellBroadcasts" msgid="1598328843619646166">"讀取區域廣播訊息"</string>
     <string name="permdesc_readCellBroadcasts" msgid="6361972776080458979">"允許應用程式讀取你裝置收到的區域廣播訊息。某些地點會發出區域廣播警示,警告你有緊急狀況發生。請注意,惡意應用程式可能會在裝置收到緊急區域廣播時,干擾裝置的效能或運作。"</string>
     <string name="permlab_subscribedFeedsRead" msgid="4756609637053353318">"讀取訂閱資訊提供"</string>
diff --git a/core/res/res/values-zu/strings.xml b/core/res/res/values-zu/strings.xml
index a5e0fed3..04091ff 100644
--- a/core/res/res/values-zu/strings.xml
+++ b/core/res/res/values-zu/strings.xml
@@ -344,6 +344,10 @@
     <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_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>
diff --git a/core/res/res/values/attrs.xml b/core/res/res/values/attrs.xml
index 0c9ae85..14f5d97 100644
--- a/core/res/res/values/attrs.xml
+++ b/core/res/res/values/attrs.xml
@@ -3755,6 +3755,16 @@
         <attr name="summary" />
     </declare-styleable>
 
+    <!-- Use <code>accessibility-shortcut-target</code> as the root tag of the XML resource that
+         describes an activity, which is referenced from the
+         <code>android.accessibilityshortcut.target</code> meta-data entry. -->
+    <declare-styleable name="AccessibilityShortcutTarget">
+        <!-- Short description of the target of accessibility shortcut purpose or behavior.-->
+        <attr name="description" />
+        <!-- Brief summary of the target of accessibility shortcut purpose or behavior. -->
+        <attr name="summary" />
+    </declare-styleable>
+
     <!-- Use <code>print-service</code> as the root tag of the XML resource that
          describes an {@link android.printservice.PrintService} service, which is
          referenced from its {@link android.printservice.PrintService#SERVICE_META_DATA}
diff --git a/core/res/res/values/attrs_manifest.xml b/core/res/res/values/attrs_manifest.xml
index 3ea8a77..a301702 100644
--- a/core/res/res/values/attrs_manifest.xml
+++ b/core/res/res/values/attrs_manifest.xml
@@ -349,10 +349,10 @@
          will be given a single shared user ID, so they can for example run
          in the same process.  Note that for them to actually get the same
          user ID, they must also be signed with the same signature.
-         @deprecated Shared user id's cause non-deterministic behaviour within the
-         package manager. As such, it's use is discouraged, deprecated, and will
-         be removed altogether in a future version of Android. Instead, proper
-         communication mechanisms such as services and providers should be used
+         @deprecated Shared user IDs cause non-deterministic behavior within the
+         package manager. As such, its use is strongly discouraged and may be
+         removed in a future version of Android. Instead, apps should use proper
+         communication mechanisms, such as services and content providers,
          to facilitate interoperability between shared components. -->
     <attr name="sharedUserId" format="string" />
 
@@ -2840,6 +2840,9 @@
 
         <!-- The name of the overlayable whose resources will be overlaid. -->
         <attr name="targetName" />
+
+        <!-- The xml file that defines the target id to overlay value mappings. -->
+        <attr name="resourcesMap" format="reference" />
     </declare-styleable>
 
     <!-- Declaration of an {@link android.content.Intent} object in XML.  May
diff --git a/core/res/res/values/config.xml b/core/res/res/values/config.xml
index e3337b7..3fef7a2d 100644
--- a/core/res/res/values/config.xml
+++ b/core/res/res/values/config.xml
@@ -433,6 +433,18 @@
         -->
     </string-array>
 
+    <!-- Configuration of network interfaces that support WakeOnLAN -->
+    <string-array translatable="false" name="config_wakeonlan_supported_interfaces">
+        <!--
+        <item>wlan0</item>
+        <item>eth0</item>
+        -->
+    </string-array>
+
+    <!-- Package name for the default CellBroadcastService module [DO NOT TRANSLATE] -->
+    <string name="cellbroadcast_default_package" translatable="false">com.android.cellbroadcastreceiver
+    </string>
+
     <!-- If the mobile hotspot feature requires provisioning, a package name and class name
         can be provided to launch a supported application that provisions the devices.
 
diff --git a/core/res/res/values/public.xml b/core/res/res/values/public.xml
index 96c0cf3..9724c41 100644
--- a/core/res/res/values/public.xml
+++ b/core/res/res/values/public.xml
@@ -3000,6 +3000,8 @@
     <public-group type="attr" first-id="0x01010607">
       <public name="importantForContentCapture" />
       <public name="forceQueryable" />
+      <!-- @hide @SystemApi -->
+      <public name="resourcesMap" />
     </public-group>
 
     <public-group type="drawable" first-id="0x010800b5">
diff --git a/core/res/res/values/strings.xml b/core/res/res/values/strings.xml
index b53a399..bf5f706 100644
--- a/core/res/res/values/strings.xml
+++ b/core/res/res/values/strings.xml
@@ -890,6 +890,16 @@
       messages. This means the app could monitor or delete messages sent to your
       device without showing them to you.</string>
 
+    <!-- Title of an application permission, listed so the user can choose whether they want to allow the application to do this.[CHAR LIMIT=NONE] -->
+    <string name="permlab_bindCellBroadcastService">Forward cell broadcast messages</string>
+    <!-- Description of an application permission, listed so the user can choose whether they want to allow the application to do this. [CHAR LIMIT=NONE] -->
+    <string name="permdesc_bindCellBroadcastService">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>
+
     <!-- Title of an application permission, listed so the user can choose whether they want to allow the application to do this. -->
     <string name="permlab_readCellBroadcasts">read cell broadcast messages</string>
     <!-- Description of an application permission, listed so the user can choose whether they want to allow the application to do this. -->
@@ -1745,11 +1755,6 @@
     <!-- Description of an application permission, listed so the user can choose whether they want to allow the application to do this. -->
     <string name="permdesc_startViewPermissionUsage">Allows the holder to start the permission usage for an app. Should never be needed for normal apps.</string>
 
-    <!-- Title of an application permission, listed so the user can choose whether they want to allow the application to do this. [CHAR_LIMIT=NONE] -->
-    <string name="permlab_accessibilityShortcutTarget">accessibility shortcut target</string>
-    <!-- Description of an application permission, listed so the user can choose whether they want to allow the application to do this. [CHAR_LIMIT=NONE] -->
-    <string name="permdesc_accessibilityShortcutTarget">Allows an app to define the accessibility shortcut target.</string>
-
     <!-- Policy administration -->
 
     <!-- Title of policy access to limiting the user's password choices -->
diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml
index e2f2b2c..363bc9d 100644
--- a/core/res/res/values/symbols.xml
+++ b/core/res/res/values/symbols.xml
@@ -747,6 +747,8 @@
   <java-symbol type="string" name="config_default_dns_server" />
   <java-symbol type="string" name="config_ethernet_iface_regex" />
   <java-symbol type="array" name="config_ethernet_interfaces" />
+  <java-symbol type="array" name="config_wakeonlan_supported_interfaces" />
+  <java-symbol type="string" name="cellbroadcast_default_package" />
   <java-symbol type="string" name="config_forceVoiceInteractionServicePackage" />
   <java-symbol type="string" name="config_mms_user_agent" />
   <java-symbol type="string" name="config_mms_user_agent_profile_url" />
diff --git a/core/tests/bugreports/Android.bp b/core/tests/bugreports/Android.bp
index d3bf0dd..e9d5bb1 100644
--- a/core/tests/bugreports/Android.bp
+++ b/core/tests/bugreports/Android.bp
@@ -20,7 +20,6 @@
         "android.test.base",
     ],
     static_libs: ["androidx.test.rules", "truth-prebuilt"],
-    test_suites: ["general-tests"],
     sdk_version: "test_current",
     platform_apis: true,
 }
diff --git a/core/tests/coretests/AndroidManifest.xml b/core/tests/coretests/AndroidManifest.xml
index 2417209..c7e54f3 100644
--- a/core/tests/coretests/AndroidManifest.xml
+++ b/core/tests/coretests/AndroidManifest.xml
@@ -1155,7 +1155,10 @@
             <intent-filter>
                 <action android:name="android.intent.action.MAIN" />
                 <category android:name="android.intent.category.FRAMEWORK_INSTRUMENTATION_TEST" />
+                <category android:name="android.intent.category.ACCESSIBILITY_SHORTCUT_TARGET" />
             </intent-filter>
+            <meta-data android:name="android.accessibilityshortcut.target"
+                       android:resource="@xml/accessibility_shortcut_test_activity"/>
         </activity>
 
         <!-- Activity-level metadata -->
diff --git a/core/tests/coretests/res/values/strings.xml b/core/tests/coretests/res/values/strings.xml
index ef915bb..f630188 100644
--- a/core/tests/coretests/res/values/strings.xml
+++ b/core/tests/coretests/res/values/strings.xml
@@ -142,4 +142,10 @@
 
     <!-- ResourcesLocaleResolutionTest -->
     <string name="dummy_string">dummy string</string>
+
+    <!-- Description of the accessibility shortcut [CHAR LIMIT=NONE] -->
+    <string name="accessibility_shortcut_description">Accessibility shortcut description</string>
+
+    <!-- Summary of the accessibility shortcut [CHAR LIMIT=NONE] -->
+    <string name="accessibility_shortcut_summary">Accessibility shortcut summary</string>
 </resources>
diff --git a/core/tests/coretests/res/xml/accessibility_shortcut_test_activity.xml b/core/tests/coretests/res/xml/accessibility_shortcut_test_activity.xml
new file mode 100644
index 0000000..60e2998
--- /dev/null
+++ b/core/tests/coretests/res/xml/accessibility_shortcut_test_activity.xml
@@ -0,0 +1,22 @@
+<?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.
+  -->
+
+<accessibility-shortcut-target xmlns:android="http://schemas.android.com/apk/res/android"
+                        android:description="@string/accessibility_shortcut_description"
+                        android:summary="@string/accessibility_shortcut_summary"
+/>
\ No newline at end of file
diff --git a/core/tests/coretests/src/android/accessibilityservice/AccessibilityShortcutInfoTest.java b/core/tests/coretests/src/android/accessibilityservice/AccessibilityShortcutInfoTest.java
new file mode 100644
index 0000000..abaeb0a
--- /dev/null
+++ b/core/tests/coretests/src/android/accessibilityservice/AccessibilityShortcutInfoTest.java
@@ -0,0 +1,98 @@
+/*
+ * 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.accessibilityservice;
+
+import static org.hamcrest.Matchers.is;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertThat;
+
+import android.content.ComponentName;
+import android.content.Context;
+import android.content.pm.ActivityInfo;
+import android.content.pm.PackageManager;
+import android.view.accessibility.AccessibilityManager;
+import android.view.accessibility.AccessibilityTestActivity;
+
+import androidx.test.filters.SmallTest;
+import androidx.test.platform.app.InstrumentationRegistry;
+import androidx.test.runner.AndroidJUnit4;
+
+import com.android.frameworks.coretests.R;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import java.util.List;
+
+/**
+ * AccessibilityShortcutInfo can only be created by system. Verify the instance creation and
+ * basic function here.
+ */
+@SmallTest
+@RunWith(AndroidJUnit4.class)
+public class AccessibilityShortcutInfoTest {
+    private Context mTargetContext;
+    private PackageManager mPackageManager;
+    private AccessibilityShortcutInfo mShortcutInfo;
+
+    @Before
+    public void setUp() {
+        mTargetContext = InstrumentationRegistry.getInstrumentation()
+                .getTargetContext();
+        mPackageManager = mTargetContext.getPackageManager();
+
+        final ComponentName testShortcutName = new ComponentName(mTargetContext,
+                AccessibilityTestActivity.class);
+        final AccessibilityManager accessibilityManager = (AccessibilityManager) mTargetContext
+                .getSystemService(Context.ACCESSIBILITY_SERVICE);
+        final List<AccessibilityShortcutInfo> infoList = accessibilityManager
+                .getInstalledAccessibilityShortcutListAsUser(
+                        mTargetContext, mTargetContext.getUserId());
+        for (AccessibilityShortcutInfo info : infoList) {
+            final ActivityInfo activityInfo = info.getActivityInfo();
+            final ComponentName name = new ComponentName(
+                    activityInfo.packageName, activityInfo.name);
+            if (name.equals(testShortcutName)) {
+                mShortcutInfo = info;
+                break;
+            }
+        }
+
+        assertNotNull("Can't find " + testShortcutName, mShortcutInfo);
+    }
+
+    @Test
+    public void testDescription() {
+        final String description = mTargetContext.getResources()
+                .getString(R.string.accessibility_shortcut_description);
+
+        assertNotNull("Can't find description string", description);
+        assertThat("Description is not correct",
+                mShortcutInfo.loadDescription(mPackageManager), is(description));
+    }
+
+    @Test
+    public void testSummary() {
+        final String summary = mTargetContext.getResources()
+                .getString(R.string.accessibility_shortcut_summary);
+
+        assertNotNull("Can't find summary string", summary);
+        assertThat("Summary is not correct",
+                mShortcutInfo.loadSummary(mPackageManager), is(summary));
+    }
+}
diff --git a/core/tests/coretests/src/android/app/servertransaction/TransactionParcelTests.java b/core/tests/coretests/src/android/app/servertransaction/TransactionParcelTests.java
index 51da0c8..39bf742 100644
--- a/core/tests/coretests/src/android/app/servertransaction/TransactionParcelTests.java
+++ b/core/tests/coretests/src/android/app/servertransaction/TransactionParcelTests.java
@@ -611,6 +611,10 @@
         }
 
         @Override
+        public void attachStartupAgents(String s) throws RemoteException {
+        }
+
+        @Override
         public void scheduleApplicationInfoChanged(ApplicationInfo applicationInfo)
                 throws RemoteException {
         }
diff --git a/core/tests/coretests/src/android/app/usage/UsageStatsTest.java b/core/tests/coretests/src/android/app/usage/UsageStatsTest.java
index 6ec3dc9..0ac00b8 100644
--- a/core/tests/coretests/src/android/app/usage/UsageStatsTest.java
+++ b/core/tests/coretests/src/android/app/usage/UsageStatsTest.java
@@ -173,7 +173,7 @@
         left.update("com.test.activity1", 400000, ACTIVITY_STOPPED, 1);
         assertEquals(left.mLastTimeUsed, 350000);
         assertEquals(left.mLastTimeVisible, 400000);
-        assertEquals(left.mActivities.get(1), ACTIVITY_STOPPED);
+        assertTrue(left.mActivities.indexOfKey(1) < 0);
         assertEquals(left.mTotalTimeInForeground, 350000 - 200000);
         assertEquals(left.mTotalTimeVisible, 400000 - 200000);
 
@@ -231,7 +231,7 @@
         left.update("com.test.activity1", 400000, ACTIVITY_STOPPED, 1);
         assertEquals(left.mLastTimeUsed, 300000);
         assertEquals(left.mLastTimeVisible, 400000);
-        assertEquals(left.mActivities.get(1), ACTIVITY_STOPPED);
+        assertTrue(left.mActivities.indexOfKey(1) < 0);
         assertEquals(left.mTotalTimeInForeground, 300000 - 200000);
         assertEquals(left.mTotalTimeVisible, 400000 - 100000);
     }
@@ -249,7 +249,7 @@
         left.update("com.test.activity1", 200000, ACTIVITY_STOPPED, 1);
         assertEquals(left.mLastTimeUsed, 200000);
         assertEquals(left.mLastTimeVisible, 200000);
-        assertEquals(left.mActivities.get(1), ACTIVITY_STOPPED);
+        assertTrue(left.mActivities.indexOfKey(1) < 0);
         assertEquals(left.mTotalTimeInForeground, 200000 - 100000);
         assertEquals(left.mTotalTimeVisible, 200000 - 100000);
 
@@ -359,14 +359,14 @@
         left.update("com.test.activity1", 550000, ACTIVITY_STOPPED, 1);
         assertEquals(left.mLastTimeUsed, 450000);
         assertEquals(left.mLastTimeVisible, 550000);
-        assertEquals(left.mActivities.get(1), ACTIVITY_STOPPED);
+        assertTrue(left.mActivities.indexOfKey(1) < 0);
         assertEquals(left.mTotalTimeInForeground, 350000);
         assertEquals(left.mTotalTimeVisible, 350000 + 100000 /*550000 - 450000*/);
 
         left.update("com.test.activity2", 650000, ACTIVITY_STOPPED, 2);
         assertEquals(left.mLastTimeUsed, 450000);
         assertEquals(left.mLastTimeVisible, 650000);
-        assertEquals(left.mActivities.get(2), ACTIVITY_STOPPED);
+        assertTrue(left.mActivities.indexOfKey(2) < 0);
         assertEquals(left.mTotalTimeInForeground, 350000);
         assertEquals(left.mTotalTimeVisible, 450000 + 100000 /*650000 - 550000*/);
     }
diff --git a/core/tests/coretests/src/android/provider/DeviceConfigTest.java b/core/tests/coretests/src/android/provider/DeviceConfigTest.java
index 23fabce..77b7f2a 100644
--- a/core/tests/coretests/src/android/provider/DeviceConfigTest.java
+++ b/core/tests/coretests/src/android/provider/DeviceConfigTest.java
@@ -17,6 +17,7 @@
 package android.provider;
 
 import static android.provider.DeviceConfig.OnPropertiesChangedListener;
+import static android.provider.DeviceConfig.Properties;
 
 import static com.google.common.truth.Truth.assertThat;
 
@@ -42,27 +43,33 @@
 @RunWith(AndroidJUnit4.class)
 @SmallTest
 public class DeviceConfigTest {
-    // TODO(b/109919982): Migrate tests to CTS
-    private static final String sNamespace = "namespace1";
-    private static final String sKey = "key1";
-    private static final String sValue = "value1";
     private static final long WAIT_FOR_PROPERTY_CHANGE_TIMEOUT_MILLIS = 2000; // 2 sec
+    private static final String DEFAULT_VALUE = "test_default_value";
+    private static final String NAMESPACE = "namespace1";
+    private static final String KEY = "key1";
+    private static final String KEY2 = "key2";
+    private static final String KEY3 = "key3";
+    private static final String VALUE = "value1";
+    private static final String VALUE2 = "value2";
+    private static final String VALUE3 = "value3";
 
     @After
     public void cleanUp() {
-        deleteViaContentProvider(sNamespace, sKey);
+        deleteViaContentProvider(NAMESPACE, KEY);
+        deleteViaContentProvider(NAMESPACE, KEY2);
+        deleteViaContentProvider(NAMESPACE, KEY3);
     }
 
     @Test
     public void getProperty_empty() {
-        String result = DeviceConfig.getProperty(sNamespace, sKey);
+        String result = DeviceConfig.getProperty(NAMESPACE, KEY);
         assertThat(result).isNull();
     }
 
     @Test
     public void getProperty_nullNamespace() {
         try {
-            DeviceConfig.getProperty(null, sKey);
+            DeviceConfig.getProperty(null, KEY);
             Assert.fail("Null namespace should have resulted in an NPE.");
         } catch (NullPointerException e) {
             // expected
@@ -72,7 +79,7 @@
     @Test
     public void getProperty_nullName() {
         try {
-            DeviceConfig.getProperty(sNamespace, null);
+            DeviceConfig.getProperty(NAMESPACE, null);
             Assert.fail("Null name should have resulted in an NPE.");
         } catch (NullPointerException e) {
             // expected
@@ -82,13 +89,13 @@
     @Test
     public void getString_empty() {
         final String default_value = "default_value";
-        final String result = DeviceConfig.getString(sNamespace, sKey, default_value);
+        final String result = DeviceConfig.getString(NAMESPACE, KEY, default_value);
         assertThat(result).isEqualTo(default_value);
     }
 
     @Test
     public void getString_nullDefault() {
-        final String result = DeviceConfig.getString(sNamespace, sKey, null);
+        final String result = DeviceConfig.getString(NAMESPACE, KEY, null);
         assertThat(result).isNull();
     }
 
@@ -96,16 +103,16 @@
     public void getString_nonEmpty() {
         final String value = "new_value";
         final String default_value = "default";
-        DeviceConfig.setProperty(sNamespace, sKey, value, false);
+        DeviceConfig.setProperty(NAMESPACE, KEY, value, false);
 
-        final String result = DeviceConfig.getString(sNamespace, sKey, default_value);
+        final String result = DeviceConfig.getString(NAMESPACE, KEY, default_value);
         assertThat(result).isEqualTo(value);
     }
 
     @Test
     public void getString_nullNamespace() {
         try {
-            DeviceConfig.getString(null, sKey, "default_value");
+            DeviceConfig.getString(null, KEY, "default_value");
             Assert.fail("Null namespace should have resulted in an NPE.");
         } catch (NullPointerException e) {
             // expected
@@ -115,7 +122,7 @@
     @Test
     public void getString_nullName() {
         try {
-            DeviceConfig.getString(sNamespace, null, "default_value");
+            DeviceConfig.getString(NAMESPACE, null, "default_value");
             Assert.fail("Null name should have resulted in an NPE.");
         } catch (NullPointerException e) {
             // expected
@@ -125,7 +132,7 @@
     @Test
     public void getBoolean_empty() {
         final boolean default_value = true;
-        final boolean result = DeviceConfig.getBoolean(sNamespace, sKey, default_value);
+        final boolean result = DeviceConfig.getBoolean(NAMESPACE, KEY, default_value);
         assertThat(result).isEqualTo(default_value);
     }
 
@@ -133,18 +140,18 @@
     public void getBoolean_valid() {
         final boolean value = true;
         final boolean default_value = false;
-        DeviceConfig.setProperty(sNamespace, sKey, String.valueOf(value), false);
+        DeviceConfig.setProperty(NAMESPACE, KEY, String.valueOf(value), false);
 
-        final boolean result = DeviceConfig.getBoolean(sNamespace, sKey, default_value);
+        final boolean result = DeviceConfig.getBoolean(NAMESPACE, KEY, default_value);
         assertThat(result).isEqualTo(value);
     }
 
     @Test
     public void getBoolean_invalid() {
         final boolean default_value = true;
-        DeviceConfig.setProperty(sNamespace, sKey, "not_a_boolean", false);
+        DeviceConfig.setProperty(NAMESPACE, KEY, "not_a_boolean", false);
 
-        final boolean result = DeviceConfig.getBoolean(sNamespace, sKey, default_value);
+        final boolean result = DeviceConfig.getBoolean(NAMESPACE, KEY, default_value);
         // Anything non-null other than case insensitive "true" parses to false.
         assertThat(result).isFalse();
     }
@@ -152,7 +159,7 @@
     @Test
     public void getBoolean_nullNamespace() {
         try {
-            DeviceConfig.getBoolean(null, sKey, false);
+            DeviceConfig.getBoolean(null, KEY, false);
             Assert.fail("Null namespace should have resulted in an NPE.");
         } catch (NullPointerException e) {
             // expected
@@ -162,7 +169,7 @@
     @Test
     public void getBoolean_nullName() {
         try {
-            DeviceConfig.getBoolean(sNamespace, null, false);
+            DeviceConfig.getBoolean(NAMESPACE, null, false);
             Assert.fail("Null name should have resulted in an NPE.");
         } catch (NullPointerException e) {
             // expected
@@ -172,7 +179,7 @@
     @Test
     public void getInt_empty() {
         final int default_value = 999;
-        final int result = DeviceConfig.getInt(sNamespace, sKey, default_value);
+        final int result = DeviceConfig.getInt(NAMESPACE, KEY, default_value);
         assertThat(result).isEqualTo(default_value);
     }
 
@@ -180,18 +187,18 @@
     public void getInt_valid() {
         final int value = 123;
         final int default_value = 999;
-        DeviceConfig.setProperty(sNamespace, sKey, String.valueOf(value), false);
+        DeviceConfig.setProperty(NAMESPACE, KEY, String.valueOf(value), false);
 
-        final int result = DeviceConfig.getInt(sNamespace, sKey, default_value);
+        final int result = DeviceConfig.getInt(NAMESPACE, KEY, default_value);
         assertThat(result).isEqualTo(value);
     }
 
     @Test
     public void getInt_invalid() {
         final int default_value = 999;
-        DeviceConfig.setProperty(sNamespace, sKey, "not_an_int", false);
+        DeviceConfig.setProperty(NAMESPACE, KEY, "not_an_int", false);
 
-        final int result = DeviceConfig.getInt(sNamespace, sKey, default_value);
+        final int result = DeviceConfig.getInt(NAMESPACE, KEY, default_value);
         // Failure to parse results in using the default value
         assertThat(result).isEqualTo(default_value);
     }
@@ -199,7 +206,7 @@
     @Test
     public void getInt_nullNamespace() {
         try {
-            DeviceConfig.getInt(null, sKey, 0);
+            DeviceConfig.getInt(null, KEY, 0);
             Assert.fail("Null namespace should have resulted in an NPE.");
         } catch (NullPointerException e) {
             // expected
@@ -209,7 +216,7 @@
     @Test
     public void getInt_nullName() {
         try {
-            DeviceConfig.getInt(sNamespace, null, 0);
+            DeviceConfig.getInt(NAMESPACE, null, 0);
             Assert.fail("Null name should have resulted in an NPE.");
         } catch (NullPointerException e) {
             // expected
@@ -219,7 +226,7 @@
     @Test
     public void getLong_empty() {
         final long default_value = 123456;
-        final long result = DeviceConfig.getLong(sNamespace, sKey, default_value);
+        final long result = DeviceConfig.getLong(NAMESPACE, KEY, default_value);
         assertThat(result).isEqualTo(default_value);
     }
 
@@ -227,18 +234,18 @@
     public void getLong_valid() {
         final long value = 456789;
         final long default_value = 123456;
-        DeviceConfig.setProperty(sNamespace, sKey, String.valueOf(value), false);
+        DeviceConfig.setProperty(NAMESPACE, KEY, String.valueOf(value), false);
 
-        final long result = DeviceConfig.getLong(sNamespace, sKey, default_value);
+        final long result = DeviceConfig.getLong(NAMESPACE, KEY, default_value);
         assertThat(result).isEqualTo(value);
     }
 
     @Test
     public void getLong_invalid() {
         final long default_value = 123456;
-        DeviceConfig.setProperty(sNamespace, sKey, "not_a_long", false);
+        DeviceConfig.setProperty(NAMESPACE, KEY, "not_a_long", false);
 
-        final long result = DeviceConfig.getLong(sNamespace, sKey, default_value);
+        final long result = DeviceConfig.getLong(NAMESPACE, KEY, default_value);
         // Failure to parse results in using the default value
         assertThat(result).isEqualTo(default_value);
     }
@@ -246,7 +253,7 @@
     @Test
     public void getLong_nullNamespace() {
         try {
-            DeviceConfig.getLong(null, sKey, 0);
+            DeviceConfig.getLong(null, KEY, 0);
             Assert.fail("Null namespace should have resulted in an NPE.");
         } catch (NullPointerException e) {
             // expected
@@ -256,7 +263,7 @@
     @Test
     public void getLong_nullName() {
         try {
-            DeviceConfig.getLong(sNamespace, null, 0);
+            DeviceConfig.getLong(NAMESPACE, null, 0);
             Assert.fail("Null name should have resulted in an NPE.");
         } catch (NullPointerException e) {
             // expected
@@ -266,7 +273,7 @@
     @Test
     public void getFloat_empty() {
         final float default_value = 123.456f;
-        final float result = DeviceConfig.getFloat(sNamespace, sKey, default_value);
+        final float result = DeviceConfig.getFloat(NAMESPACE, KEY, default_value);
         assertThat(result).isEqualTo(default_value);
     }
 
@@ -274,18 +281,18 @@
     public void getFloat_valid() {
         final float value = 456.789f;
         final float default_value = 123.456f;
-        DeviceConfig.setProperty(sNamespace, sKey, String.valueOf(value), false);
+        DeviceConfig.setProperty(NAMESPACE, KEY, String.valueOf(value), false);
 
-        final float result = DeviceConfig.getFloat(sNamespace, sKey, default_value);
+        final float result = DeviceConfig.getFloat(NAMESPACE, KEY, default_value);
         assertThat(result).isEqualTo(value);
     }
 
     @Test
     public void getFloat_invalid() {
         final float default_value = 123.456f;
-        DeviceConfig.setProperty(sNamespace, sKey, "not_a_float", false);
+        DeviceConfig.setProperty(NAMESPACE, KEY, "not_a_float", false);
 
-        final float result = DeviceConfig.getFloat(sNamespace, sKey, default_value);
+        final float result = DeviceConfig.getFloat(NAMESPACE, KEY, default_value);
         // Failure to parse results in using the default value
         assertThat(result).isEqualTo(default_value);
     }
@@ -293,7 +300,7 @@
     @Test
     public void getFloat_nullNamespace() {
         try {
-            DeviceConfig.getFloat(null, sKey, 0);
+            DeviceConfig.getFloat(null, KEY, 0);
             Assert.fail("Null namespace should have resulted in an NPE.");
         } catch (NullPointerException e) {
             // expected
@@ -303,7 +310,7 @@
     @Test
     public void getFloat_nullName() {
         try {
-            DeviceConfig.getFloat(sNamespace, null, 0);
+            DeviceConfig.getFloat(NAMESPACE, null, 0);
             Assert.fail("Null name should have resulted in an NPE.");
         } catch (NullPointerException e) {
             // expected
@@ -313,7 +320,7 @@
     @Test
     public void setProperty_nullNamespace() {
         try {
-            DeviceConfig.setProperty(null, sKey, sValue, false);
+            DeviceConfig.setProperty(null, KEY, VALUE, false);
             Assert.fail("Null namespace should have resulted in an NPE.");
         } catch (NullPointerException e) {
             // expected
@@ -323,7 +330,7 @@
     @Test
     public void setProperty_nullName() {
         try {
-            DeviceConfig.setProperty(sNamespace, null, sValue, false);
+            DeviceConfig.setProperty(NAMESPACE, null, VALUE, false);
             Assert.fail("Null name should have resulted in an NPE.");
         } catch (NullPointerException e) {
             // expected
@@ -332,16 +339,16 @@
 
     @Test
     public void setAndGetProperty_sameNamespace() {
-        DeviceConfig.setProperty(sNamespace, sKey, sValue, false);
-        String result = DeviceConfig.getProperty(sNamespace, sKey);
-        assertThat(result).isEqualTo(sValue);
+        DeviceConfig.setProperty(NAMESPACE, KEY, VALUE, false);
+        String result = DeviceConfig.getProperty(NAMESPACE, KEY);
+        assertThat(result).isEqualTo(VALUE);
     }
 
     @Test
     public void setAndGetProperty_differentNamespace() {
         String newNamespace = "namespace2";
-        DeviceConfig.setProperty(sNamespace, sKey, sValue, false);
-        String result = DeviceConfig.getProperty(newNamespace, sKey);
+        DeviceConfig.setProperty(NAMESPACE, KEY, VALUE, false);
+        String result = DeviceConfig.getProperty(newNamespace, KEY);
         assertThat(result).isNull();
     }
 
@@ -349,41 +356,147 @@
     public void setAndGetProperty_multipleNamespaces() {
         String newNamespace = "namespace2";
         String newValue = "value2";
-        DeviceConfig.setProperty(sNamespace, sKey, sValue, false);
-        DeviceConfig.setProperty(newNamespace, sKey, newValue, false);
-        String result = DeviceConfig.getProperty(sNamespace, sKey);
-        assertThat(result).isEqualTo(sValue);
-        result = DeviceConfig.getProperty(newNamespace, sKey);
+        DeviceConfig.setProperty(NAMESPACE, KEY, VALUE, false);
+        DeviceConfig.setProperty(newNamespace, KEY, newValue, false);
+        String result = DeviceConfig.getProperty(NAMESPACE, KEY);
+        assertThat(result).isEqualTo(VALUE);
+        result = DeviceConfig.getProperty(newNamespace, KEY);
         assertThat(result).isEqualTo(newValue);
 
         // clean up
-        deleteViaContentProvider(newNamespace, sKey);
+        deleteViaContentProvider(newNamespace, KEY);
     }
 
     @Test
     public void setAndGetProperty_overrideValue() {
         String newValue = "value2";
-        DeviceConfig.setProperty(sNamespace, sKey, sValue, false);
-        DeviceConfig.setProperty(sNamespace, sKey, newValue, false);
-        String result = DeviceConfig.getProperty(sNamespace, sKey);
+        DeviceConfig.setProperty(NAMESPACE, KEY, VALUE, false);
+        DeviceConfig.setProperty(NAMESPACE, KEY, newValue, false);
+        String result = DeviceConfig.getProperty(NAMESPACE, KEY);
         assertThat(result).isEqualTo(newValue);
     }
 
     @Test
+    public void getProperties_fullNamespace() {
+        Properties properties = DeviceConfig.getProperties(NAMESPACE);
+        assertThat(properties.getKeyset()).isEmpty();
+
+        DeviceConfig.setProperty(NAMESPACE, KEY, VALUE, false);
+        DeviceConfig.setProperty(NAMESPACE, KEY2, VALUE2, false);
+        properties = DeviceConfig.getProperties(NAMESPACE);
+        assertThat(properties.getKeyset()).containsExactly(KEY, KEY2);
+        assertThat(properties.getString(KEY, DEFAULT_VALUE)).isEqualTo(VALUE);
+        assertThat(properties.getString(KEY2, DEFAULT_VALUE)).isEqualTo(VALUE2);
+
+        DeviceConfig.setProperty(NAMESPACE, KEY, VALUE3, false);
+        properties = DeviceConfig.getProperties(NAMESPACE);
+        assertThat(properties.getKeyset()).containsExactly(KEY, KEY2);
+        assertThat(properties.getString(KEY, DEFAULT_VALUE)).isEqualTo(VALUE3);
+        assertThat(properties.getString(KEY2, DEFAULT_VALUE)).isEqualTo(VALUE2);
+    }
+
+    @Test
+    public void getProperties_getString() {
+        DeviceConfig.setProperty(NAMESPACE, KEY, VALUE, false);
+        DeviceConfig.setProperty(NAMESPACE, KEY2, VALUE2, false);
+
+        Properties properties = DeviceConfig.getProperties(NAMESPACE, KEY, KEY2);
+        assertThat(properties.getKeyset()).containsExactly(KEY, KEY2);
+        assertThat(properties.getString(KEY, DEFAULT_VALUE)).isEqualTo(VALUE);
+        assertThat(properties.getString(KEY2, DEFAULT_VALUE)).isEqualTo(VALUE2);
+    }
+
+    @Test
+    public void getProperties_getBoolean() {
+        DeviceConfig.setProperty(NAMESPACE, KEY, "true", false);
+        DeviceConfig.setProperty(NAMESPACE, KEY2, "false", false);
+        DeviceConfig.setProperty(NAMESPACE, KEY3, "not a valid boolean", false);
+
+        Properties properties = DeviceConfig.getProperties(NAMESPACE, KEY, KEY2, KEY3);
+        assertThat(properties.getKeyset()).containsExactly(KEY, KEY2, KEY3);
+        assertThat(properties.getBoolean(KEY, true)).isTrue();
+        assertThat(properties.getBoolean(KEY, false)).isTrue();
+        assertThat(properties.getBoolean(KEY2, true)).isFalse();
+        assertThat(properties.getBoolean(KEY2, false)).isFalse();
+        // KEY3 was set to garbage, anything nonnull but "true" will parse as false
+        assertThat(properties.getBoolean(KEY3, true)).isFalse();
+        assertThat(properties.getBoolean(KEY3, false)).isFalse();
+        // If a key was not set, it will return the default value
+        assertThat(properties.getBoolean("missing_key", true)).isTrue();
+        assertThat(properties.getBoolean("missing_key", false)).isFalse();
+    }
+
+    @Test
+    public void getProperties_getInt() {
+        final int value = 101;
+
+        DeviceConfig.setProperty(NAMESPACE, KEY, Integer.toString(value), false);
+        DeviceConfig.setProperty(NAMESPACE, KEY2, "not a valid int", false);
+
+        Properties properties = DeviceConfig.getProperties(NAMESPACE, KEY, KEY2);
+        assertThat(properties.getKeyset()).containsExactly(KEY, KEY2);
+        assertThat(properties.getInt(KEY, -1)).isEqualTo(value);
+        // KEY2 was set to garbage, the default value is returned if an int cannot be parsed
+        assertThat(properties.getInt(KEY2, -1)).isEqualTo(-1);
+    }
+
+    @Test
+    public void getProperties_getFloat() {
+        final float value = 101.010f;
+
+        DeviceConfig.setProperty(NAMESPACE, KEY, Float.toString(value), false);
+        DeviceConfig.setProperty(NAMESPACE, KEY2, "not a valid float", false);
+
+        Properties properties = DeviceConfig.getProperties(NAMESPACE, KEY, KEY2);
+        assertThat(properties.getKeyset()).containsExactly(KEY, KEY2);
+        assertThat(properties.getFloat(KEY, -1.0f)).isEqualTo(value);
+        // KEY2 was set to garbage, the default value is returned if a float cannot be parsed
+        assertThat(properties.getFloat(KEY2, -1.0f)).isEqualTo(-1.0f);
+    }
+
+    @Test
+    public void getProperties_getLong() {
+        final long value = 101;
+
+        DeviceConfig.setProperty(NAMESPACE, KEY, Long.toString(value), false);
+        DeviceConfig.setProperty(NAMESPACE, KEY2, "not a valid long", false);
+
+        Properties properties = DeviceConfig.getProperties(NAMESPACE, KEY, KEY2);
+        assertThat(properties.getKeyset()).containsExactly(KEY, KEY2);
+        assertThat(properties.getLong(KEY, -1)).isEqualTo(value);
+        // KEY2 was set to garbage, the default value is returned if a long cannot be parsed
+        assertThat(properties.getLong(KEY2, -1)).isEqualTo(-1);
+    }
+
+    @Test
+    public void getProperties_defaults() {
+        DeviceConfig.setProperty(NAMESPACE, KEY, VALUE, false);
+        DeviceConfig.setProperty(NAMESPACE, KEY3, VALUE3, false);
+
+        Properties properties = DeviceConfig.getProperties(NAMESPACE, KEY, KEY2);
+        assertThat(properties.getKeyset()).containsExactly(KEY);
+        assertThat(properties.getString(KEY, DEFAULT_VALUE)).isEqualTo(VALUE);
+        // not set in DeviceConfig, but requested in getProperties
+        assertThat(properties.getString(KEY2, DEFAULT_VALUE)).isEqualTo(DEFAULT_VALUE);
+        // set in DeviceConfig, but not requested in getProperties
+        assertThat(properties.getString(KEY3, DEFAULT_VALUE)).isEqualTo(DEFAULT_VALUE);
+    }
+
+    @Test
     public void testOnPropertiesChangedListener() throws InterruptedException {
         final CountDownLatch countDownLatch = new CountDownLatch(1);
 
         OnPropertiesChangedListener changeListener = (properties) -> {
-            assertThat(properties.getNamespace()).isEqualTo(sNamespace);
-            assertThat(properties.getKeyset()).contains(sKey);
-            assertThat(properties.getString(sKey, "default_value")).isEqualTo(sValue);
+            assertThat(properties.getNamespace()).isEqualTo(NAMESPACE);
+            assertThat(properties.getKeyset()).contains(KEY);
+            assertThat(properties.getString(KEY, "default_value")).isEqualTo(VALUE);
             countDownLatch.countDown();
         };
 
         try {
-            DeviceConfig.addOnPropertiesChangedListener(sNamespace,
+            DeviceConfig.addOnPropertiesChangedListener(NAMESPACE,
                     ActivityThread.currentApplication().getMainExecutor(), changeListener);
-            DeviceConfig.setProperty(sNamespace, sKey, sValue, false);
+            DeviceConfig.setProperty(NAMESPACE, KEY, VALUE, false);
             assertThat(countDownLatch.await(
                     WAIT_FOR_PROPERTY_CHANGE_TIMEOUT_MILLIS, TimeUnit.MILLISECONDS)).isTrue();
         } catch (InterruptedException e) {
diff --git a/core/tests/coretests/src/android/view/ViewGroupTest.java b/core/tests/coretests/src/android/view/ViewGroupTest.java
index 979a839..506cc2d 100644
--- a/core/tests/coretests/src/android/view/ViewGroupTest.java
+++ b/core/tests/coretests/src/android/view/ViewGroupTest.java
@@ -16,9 +16,14 @@
 
 package android.view;
 
-import static androidx.test.InstrumentationRegistry.getContext;
+import static androidx.test.platform.app.InstrumentationRegistry.getInstrumentation;
 
 import static org.junit.Assert.assertEquals;
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.Mockito.doReturn;
+import static org.mockito.Mockito.never;
+import static org.mockito.Mockito.spy;
+import static org.mockito.Mockito.verify;
 
 import android.content.Context;
 import android.graphics.Region;
@@ -39,6 +44,60 @@
 @SmallTest
 public class ViewGroupTest {
 
+    @Test
+    public void testDispatchMouseEventsUnderCursor() {
+        final Context context = getInstrumentation().getContext();
+        final TestView viewGroup = new TestView(context, 0 /* left */, 0 /* top */,
+                200 /* right */, 200 /* bottom */);
+        final TestView viewA = spy(new TestView(context, 0 /* left */, 0 /* top */,
+                100 /* right */, 200 /* bottom */));
+        final TestView viewB = spy(new TestView(context, 100 /* left */, 0 /* top */,
+                200 /* right */, 200 /* bottom */));
+
+        viewGroup.addView(viewA);
+        viewGroup.addView(viewB);
+
+        // Make sure all of them handle touch events dispatched to them.
+        doReturn(true).when(viewA).dispatchTouchEvent(any());
+        doReturn(true).when(viewB).dispatchTouchEvent(any());
+
+        MotionEvent.PointerProperties[] properties = new MotionEvent.PointerProperties[2];
+        properties[0] = new MotionEvent.PointerProperties();
+        properties[0].id = 0;
+        properties[0].toolType = MotionEvent.TOOL_TYPE_FINGER;
+        properties[1] = new MotionEvent.PointerProperties();
+        properties[1].id = 1;
+        properties[1].toolType = MotionEvent.TOOL_TYPE_FINGER;
+
+        MotionEvent.PointerCoords[] coords = new MotionEvent.PointerCoords[2];
+        coords[0] = new MotionEvent.PointerCoords();
+        coords[0].x = 80;
+        coords[0].y = 100;
+        coords[1] = new MotionEvent.PointerCoords();
+        coords[1].x = 240;
+        coords[1].y = 100;
+
+        MotionEvent event;
+        // Make sure the down event is active with a pointer which coordinate is different from the
+        // cursor position, which is the midpoint of all 2 pointers above.
+        event = MotionEvent.obtain(0 /* downTime */, 0 /* eventTime */, MotionEvent.ACTION_DOWN,
+                2 /* pointerCount */, properties, coords, 0 /* metaState */, 0 /* buttonState */,
+                0 /* xPrecision */, 0 /* yPrecision */, 0 /* deviceId */, 0 /* edgeFlags */,
+                InputDevice.SOURCE_MOUSE, 0 /* flags */);
+        viewGroup.dispatchTouchEvent(event);
+        verify(viewB).dispatchTouchEvent(event);
+
+        event = MotionEvent.obtain(0 /* downTime */, 0 /* eventTime */,
+                MotionEvent.ACTION_POINTER_DOWN | (1 << MotionEvent.ACTION_POINTER_INDEX_SHIFT),
+                2 /* pointerCount */, properties, coords, 0 /* metaState */, 0 /* buttonState */,
+                0 /* xPrecision */, 0 /* yPrecision */, 0 /* deviceId */, 0 /* edgeFlags */,
+                InputDevice.SOURCE_MOUSE, 0 /* flags */);
+        viewGroup.dispatchTouchEvent(event);
+        verify(viewB).dispatchTouchEvent(event);
+
+        verify(viewA, never()).dispatchTouchEvent(any());
+    }
+
     /**
      * Test if {@link ViewGroup#subtractObscuredTouchableRegion} works as expected.
      *
@@ -59,7 +118,7 @@
      */
     @Test
     public void testSubtractObscuredTouchableRegion() {
-        final Context context = getContext();
+        final Context context = getInstrumentation().getContext();
         final TestView viewA = new TestView(context, 8 /* right */);
         final TestView viewB = new TestView(context, 6 /* right */);
         final TestView viewC = new TestView(context, 10 /* right */);
@@ -119,10 +178,14 @@
                 (contain ? "" : " not"), x), contain, region.contains(x, 0 /* y */));
     }
 
-    private static class TestView extends ViewGroup {
+    public static class TestView extends ViewGroup {
         TestView(Context context, int right) {
+            this(context, 0 /* left */, 0 /* top */, right, 1 /* bottom */);
+        }
+
+        TestView(Context context, int left, int top, int right, int bottom) {
             super(context);
-            setFrame(0 /* left */, 0 /* top */, right, 1 /* bottom */);
+            setFrame(left, top, right, bottom);
         }
 
         @Override
diff --git a/core/tests/coretests/src/android/view/accessibility/AccessibilityServiceConnectionImpl.java b/core/tests/coretests/src/android/view/accessibility/AccessibilityServiceConnectionImpl.java
index 682416c..3586216a 100644
--- a/core/tests/coretests/src/android/view/accessibility/AccessibilityServiceConnectionImpl.java
+++ b/core/tests/coretests/src/android/view/accessibility/AccessibilityServiceConnectionImpl.java
@@ -23,8 +23,6 @@
 import android.os.Bundle;
 import android.os.IBinder;
 
-import java.util.List;
-
 /**
  * Stub implementation of IAccessibilityServiceConnection so each test doesn't need to implement
  * all of the methods
@@ -73,7 +71,7 @@
         return null;
     }
 
-    public List<AccessibilityWindowInfo> getWindows() {
+    public AccessibilityWindowInfo.WindowListSparseArray getWindows() {
         return null;
     }
 
diff --git a/core/tests/featureflagtests/OWNERS b/core/tests/featureflagtests/OWNERS
index 1a8fd2b..2ff4f5a 100644
--- a/core/tests/featureflagtests/OWNERS
+++ b/core/tests/featureflagtests/OWNERS
@@ -1,2 +1,2 @@
 sbasi@google.com
-zhfan@google.com
\ No newline at end of file
+tmfang@google.com
\ No newline at end of file
diff --git a/data/etc/hiddenapi-package-whitelist.xml b/data/etc/hiddenapi-package-whitelist.xml
index 054f68b..07a5617 100644
--- a/data/etc/hiddenapi-package-whitelist.xml
+++ b/data/etc/hiddenapi-package-whitelist.xml
@@ -53,6 +53,10 @@
   <hidden-api-whitelisted-app package="com.android.providers.media" />
   <hidden-api-whitelisted-app package="com.android.providers.tv" />
   <hidden-api-whitelisted-app package="com.android.providers.userdictionary" />
+  <!-- TODO (b/141954427): Remove networkstack -->
+  <hidden-api-whitelisted-app package="com.android.networkstack" />
+  <!-- TODO (b/141954427): Remove wifistack -->
+  <hidden-api-whitelisted-app package="com.android.wifi" />
   <hidden-api-whitelisted-app package="com.android.smspush" />
   <hidden-api-whitelisted-app package="com.android.spare_parts" />
   <hidden-api-whitelisted-app package="com.android.statementservice" />
diff --git a/data/etc/privapp-permissions-platform.xml b/data/etc/privapp-permissions-platform.xml
index 89523d6..10f6b69 100644
--- a/data/etc/privapp-permissions-platform.xml
+++ b/data/etc/privapp-permissions-platform.xml
@@ -127,6 +127,7 @@
         <permission name="android.permission.ACCESS_IMS_CALL_SERVICE"/>
         <permission name="android.permission.BIND_CARRIER_MESSAGING_SERVICE"/>
         <permission name="android.permission.BIND_CARRIER_SERVICES"/>
+        <permission name="android.permission.BIND_CELL_BROADCAST_SERVICE"/>
         <permission name="android.permission.BIND_IMS_SERVICE"/>
         <permission name="android.permission.BIND_TELEPHONY_DATA_SERVICE"/>
         <permission name="android.permission.BIND_VISUAL_VOICEMAIL_SERVICE"/>
@@ -353,7 +354,7 @@
         <permission name="android.permission.MANAGE_DYNAMIC_SYSTEM"/>
     </privapp-permissions>
 
-    <privapp-permissions package="com.android.server.wifistack">
+    <privapp-permissions package="com.android.wifi">
         <permission name="android.permission.CHANGE_CONFIGURATION"/>
         <permission name="android.permission.CONNECTIVITY_INTERNAL"/>
         <permission name="android.permission.DUMP"/>
diff --git a/data/etc/services.core.protolog.json b/data/etc/services.core.protolog.json
index a2402e2..34b3951 100644
--- a/data/etc/services.core.protolog.json
+++ b/data/etc/services.core.protolog.json
@@ -823,6 +823,12 @@
       "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",
@@ -925,12 +931,6 @@
       "group": "WM_DEBUG_APP_TRANSITIONS",
       "at": "com\/android\/server\/wm\/WindowState.java"
     },
-    "-117925665": {
-      "message": "addAppToken: %s task=%s at %d",
-      "level": "VERBOSE",
-      "group": "WM_DEBUG_ADD_REMOVE",
-      "at": "com\/android\/server\/wm\/ActivityRecord.java"
-    },
     "-116086365": {
       "message": "******************** ENABLING SCREEN!",
       "level": "INFO",
diff --git a/graphics/java/android/graphics/BLASTBufferQueue.java b/graphics/java/android/graphics/BLASTBufferQueue.java
new file mode 100644
index 0000000..8c6a9371
--- /dev/null
+++ b/graphics/java/android/graphics/BLASTBufferQueue.java
@@ -0,0 +1,67 @@
+/*
+ * 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.graphics;
+
+import android.view.Surface;
+import android.view.SurfaceControl;
+
+/**
+ * @hide
+ */
+public final class BLASTBufferQueue {
+    // Note: This field is accessed by native code.
+    private long mNativeObject; // BLASTBufferQueue*
+
+    private static native long nativeCreate(long surfaceControl, long width, long height);
+    private static native void nativeDestroy(long ptr);
+    private static native Surface nativeGetSurface(long ptr);
+    private static native void nativeSetNextTransaction(long ptr, long transactionPtr);
+    private static native void nativeUpdate(long ptr, long surfaceControl, long width, long height);
+
+    /** Create a new connection with the surface flinger. */
+    public BLASTBufferQueue(SurfaceControl sc, int width, int height) {
+        mNativeObject = nativeCreate(sc.mNativeObject, width, height);
+    }
+
+    public void destroy() {
+        nativeDestroy(mNativeObject);
+    }
+
+    public Surface getSurface() {
+        return nativeGetSurface(mNativeObject);
+    }
+
+    public void setNextTransaction(SurfaceControl.Transaction t) {
+        nativeSetNextTransaction(mNativeObject, t.mNativeObject);
+    }
+
+    public void update(SurfaceControl sc, int width, int height) {
+        nativeUpdate(mNativeObject, sc.mNativeObject, width, height);
+    }
+
+    @Override
+    protected void finalize() throws Throwable {
+        try {
+            if (mNativeObject != 0) {
+                nativeDestroy(mNativeObject);
+            }
+        } finally {
+            super.finalize();
+        }
+    }
+}
+
diff --git a/graphics/java/android/graphics/ImageDecoder.java b/graphics/java/android/graphics/ImageDecoder.java
index 150a941..6619dba 100644
--- a/graphics/java/android/graphics/ImageDecoder.java
+++ b/graphics/java/android/graphics/ImageDecoder.java
@@ -286,6 +286,9 @@
 
                 return createFromStream(is, true, preferAnimation, this);
             }
+            if (assetFd == null) {
+                throw new FileNotFoundException(mUri.toString());
+            }
             return createFromAssetFileDescriptor(assetFd, preferAnimation, this);
         }
     }
@@ -341,6 +344,9 @@
     @NonNull
     private static ImageDecoder createFromAssetFileDescriptor(@NonNull AssetFileDescriptor assetFd,
             boolean preferAnimation, Source source) throws IOException {
+        if (assetFd == null) {
+            throw new FileNotFoundException();
+        }
         final FileDescriptor fd = assetFd.getFileDescriptor();
         final long offset = assetFd.getStartOffset();
 
diff --git a/graphics/java/android/graphics/RenderNode.java b/graphics/java/android/graphics/RenderNode.java
index 0e635c7..17e3b44 100644
--- a/graphics/java/android/graphics/RenderNode.java
+++ b/graphics/java/android/graphics/RenderNode.java
@@ -1380,7 +1380,22 @@
      * @return Approximate memory usage in bytes.
      */
     public @BytesLong long computeApproximateMemoryUsage() {
-        return nGetDebugSize(mNativeRenderNode);
+        return nGetUsageSize(mNativeRenderNode);
+    }
+
+    /**
+     * Gets the approximate amount of memory allocated for the RenderNode for debug purposes.
+     * Does not include the memory allocated by any child RenderNodes nor any bitmaps, only the
+     * memory allocated for this RenderNode and any data it owns.
+     *
+     * The difference between this and {@link #computeApproximateMemoryUsage()} is this includes
+     * memory allocated but not used. In particular structures such as DisplayLists are similar
+     * to things like ArrayLists - they need to resize as commands are added to them. As such,
+     * memory used can be less than memory allocated.
+     *
+     * @hide */
+    public @BytesLong long computeApproximateMemoryAllocated() {
+        return nGetAllocatedSize(mNativeRenderNode);
     }
 
     /**
@@ -1485,7 +1500,8 @@
 
     private static native void nOutput(long renderNode);
 
-    private static native int nGetDebugSize(long renderNode);
+    private static native int nGetUsageSize(long renderNode);
+    private static native int nGetAllocatedSize(long renderNode);
 
     private static native void nRequestPositionUpdates(long renderNode,
             PositionUpdateListener callback);
diff --git a/graphics/java/android/graphics/drawable/GradientDrawable.java b/graphics/java/android/graphics/drawable/GradientDrawable.java
index 96ac0f9..c6586ec 100644
--- a/graphics/java/android/graphics/drawable/GradientDrawable.java
+++ b/graphics/java/android/graphics/drawable/GradientDrawable.java
@@ -97,6 +97,14 @@
  * @attr ref android.R.styleable#GradientDrawablePadding_bottom
  */
 public class GradientDrawable extends Drawable {
+
+    /**
+     * Flag to determine if we should wrap negative gradient angle measurements
+     * for API levels that support it
+     * @hide
+     */
+    public static boolean sWrapNegativeAngleMeasurements = true;
+
     /**
      * Shape is a rectangle, possibly with rounded corners
      */
@@ -151,6 +159,9 @@
     /** Radius is a fraction of the bounds size. */
     private static final int RADIUS_TYPE_FRACTION_PARENT = 2;
 
+    /** Default orientation for GradientDrawable **/
+    private static final Orientation DEFAULT_ORIENTATION = Orientation.TOP_BOTTOM;
+
     /** @hide */
     @IntDef({RADIUS_TYPE_PIXELS, RADIUS_TYPE_FRACTION, RADIUS_TYPE_FRACTION_PARENT})
     @Retention(RetentionPolicy.SOURCE)
@@ -207,7 +218,7 @@
     }
 
     public GradientDrawable() {
-        this(new GradientState(Orientation.TOP_BOTTOM, null), null);
+        this(new GradientState(DEFAULT_ORIENTATION, null), null);
     }
 
     /**
@@ -1757,33 +1768,48 @@
         }
 
         int angle = (int) a.getFloat(R.styleable.GradientDrawableGradient_angle, st.mAngle);
-        st.mAngle = ((angle % 360) + 360) % 360; // offset negative angle measures
 
-        switch (st.mAngle) {
-            case 0:
-                st.mOrientation = Orientation.LEFT_RIGHT;
-                break;
-            case 45:
-                st.mOrientation = Orientation.BL_TR;
-                break;
-            case 90:
-                st.mOrientation = Orientation.BOTTOM_TOP;
-                break;
-            case 135:
-                st.mOrientation = Orientation.BR_TL;
-                break;
-            case 180:
-                st.mOrientation = Orientation.RIGHT_LEFT;
-                break;
-            case 225:
-                st.mOrientation = Orientation.TR_BL;
-                break;
-            case 270:
-                st.mOrientation = Orientation.TOP_BOTTOM;
-                break;
-            case 315:
-                st.mOrientation = Orientation.TL_BR;
-                break;
+        // GradientDrawable historically has not parsed negative angle measurements and always
+        // stays on the default orientation for API levels older than Q.
+        // Only configure the orientation if the angle is greater than zero.
+        // Otherwise fallback on Orientation.TOP_BOTTOM
+        // In Android Q and later, actually wrap the negative angle measurement to the correct
+        // value
+        if (sWrapNegativeAngleMeasurements) {
+            st.mAngle = ((angle % 360) + 360) % 360; // offset negative angle measures
+        } else {
+            st.mAngle = angle % 360;
+        }
+
+        if (st.mAngle >= 0) {
+            switch (st.mAngle) {
+                case 0:
+                    st.mOrientation = Orientation.LEFT_RIGHT;
+                    break;
+                case 45:
+                    st.mOrientation = Orientation.BL_TR;
+                    break;
+                case 90:
+                    st.mOrientation = Orientation.BOTTOM_TOP;
+                    break;
+                case 135:
+                    st.mOrientation = Orientation.BR_TL;
+                    break;
+                case 180:
+                    st.mOrientation = Orientation.RIGHT_LEFT;
+                    break;
+                case 225:
+                    st.mOrientation = Orientation.TR_BL;
+                    break;
+                case 270:
+                    st.mOrientation = Orientation.TOP_BOTTOM;
+                    break;
+                case 315:
+                    st.mOrientation = Orientation.TL_BR;
+                    break;
+            }
+        } else {
+            st.mOrientation = DEFAULT_ORIENTATION;
         }
 
         final TypedValue tv = a.peekValue(R.styleable.GradientDrawableGradient_gradientRadius);
diff --git a/keystore/java/android/security/KeyChain.java b/keystore/java/android/security/KeyChain.java
index 1829d2f..bf23634 100644
--- a/keystore/java/android/security/KeyChain.java
+++ b/keystore/java/android/security/KeyChain.java
@@ -343,6 +343,16 @@
     public static final int KEY_ATTESTATION_FAILURE = 4;
 
     /**
+     * Used by DPC or delegated app in
+     * {@link android.app.admin.DeviceAdminReceiver#onChoosePrivateKeyAlias} or
+     * {@link android.app.admin.DelegatedAdminReceiver#onChoosePrivateKeyAlias} to identify that
+     * the requesting app is not granted access to any key, and nor will the user be able to grant
+     * access manually.
+     */
+    public static final String KEY_ALIAS_SELECTION_DENIED =
+            "alias-selection-denied-ef829e15-210a-409d-96c9-ee684fc41972";
+
+    /**
      * Returns an {@code Intent} that can be used for credential
      * installation. The intent may be used without any extras, in
      * which case the user will be able to install credentials from
diff --git a/libs/androidfw/ResourceTypes.cpp b/libs/androidfw/ResourceTypes.cpp
index 5353869..3fe2c5b 100644
--- a/libs/androidfw/ResourceTypes.cpp
+++ b/libs/androidfw/ResourceTypes.cpp
@@ -1063,6 +1063,11 @@
     return (mError == NO_ERROR) ? mHeader->header.size : 0;
 }
 
+const void* ResStringPool::data() const
+{
+    return mHeader;
+}
+
 bool ResStringPool::isSorted() const
 {
     return (mHeader->flags&ResStringPool_header::SORTED_FLAG)!=0;
diff --git a/libs/androidfw/include/androidfw/ResourceTypes.h b/libs/androidfw/include/androidfw/ResourceTypes.h
index fc635aa..c8ace90 100644
--- a/libs/androidfw/include/androidfw/ResourceTypes.h
+++ b/libs/androidfw/include/androidfw/ResourceTypes.h
@@ -523,6 +523,8 @@
     size_t size() const;
     size_t styleCount() const;
     size_t bytes() const;
+    const void* data() const;
+
 
     bool isSorted() const;
     bool isUTF8() const;
diff --git a/libs/hwui/RecordingCanvas.h b/libs/hwui/RecordingCanvas.h
index a79b7c0..322eff2 100644
--- a/libs/hwui/RecordingCanvas.h
+++ b/libs/hwui/RecordingCanvas.h
@@ -69,6 +69,7 @@
 
     bool hasText() const { return mHasText; }
     size_t usedSize() const { return fUsed; }
+    size_t allocatedSize() const { return fReserved; }
 
 private:
     friend class RecordingCanvas;
diff --git a/libs/hwui/RenderNode.cpp b/libs/hwui/RenderNode.cpp
index 8eb5e3d..6761435 100644
--- a/libs/hwui/RenderNode.cpp
+++ b/libs/hwui/RenderNode.cpp
@@ -108,7 +108,7 @@
     output << std::endl;
 }
 
-int RenderNode::getDebugSize() {
+int RenderNode::getUsageSize() {
     int size = sizeof(RenderNode);
     if (mStagingDisplayList) {
         size += mStagingDisplayList->getUsedSize();
@@ -119,6 +119,18 @@
     return size;
 }
 
+int RenderNode::getAllocatedSize() {
+    int size = sizeof(RenderNode);
+    if (mStagingDisplayList) {
+        size += mStagingDisplayList->getAllocatedSize();
+    }
+    if (mDisplayList && mDisplayList != mStagingDisplayList) {
+        size += mDisplayList->getAllocatedSize();
+    }
+    return size;
+}
+
+
 void RenderNode::prepareTree(TreeInfo& info) {
     ATRACE_CALL();
     LOG_ALWAYS_FATAL_IF(!info.damageAccumulator, "DamageAccumulator missing");
diff --git a/libs/hwui/RenderNode.h b/libs/hwui/RenderNode.h
index c6db7f1..d55e5b0 100644
--- a/libs/hwui/RenderNode.h
+++ b/libs/hwui/RenderNode.h
@@ -102,7 +102,8 @@
     ANDROID_API void setStagingDisplayList(DisplayList* newData);
 
     ANDROID_API void output();
-    ANDROID_API int getDebugSize();
+    ANDROID_API int getUsageSize();
+    ANDROID_API int getAllocatedSize();
 
     bool isRenderable() const { return mDisplayList && !mDisplayList->isEmpty(); }
 
diff --git a/libs/hwui/pipeline/skia/SkiaDisplayList.h b/libs/hwui/pipeline/skia/SkiaDisplayList.h
index e3c3273..cdd00db 100644
--- a/libs/hwui/pipeline/skia/SkiaDisplayList.h
+++ b/libs/hwui/pipeline/skia/SkiaDisplayList.h
@@ -47,6 +47,7 @@
 class SkiaDisplayList {
 public:
     size_t getUsedSize() { return allocator.usedSize() + mDisplayList.usedSize(); }
+    size_t getAllocatedSize() { return allocator.allocatedSize() + mDisplayList.allocatedSize(); }
 
     ~SkiaDisplayList() {
         /* Given that we are using a LinearStdAllocator to store some of the
diff --git a/libs/hwui/renderthread/CacheManager.cpp b/libs/hwui/renderthread/CacheManager.cpp
index fc26813..8eb8153 100644
--- a/libs/hwui/renderthread/CacheManager.cpp
+++ b/libs/hwui/renderthread/CacheManager.cpp
@@ -39,7 +39,7 @@
 // to the screen resolution. This is meant to be a conservative default based on
 // that analysis. The 4.0f is used because the default pixel format is assumed to
 // be ARGB_8888.
-#define SURFACE_SIZE_MULTIPLIER (12.0f * 4.0f)
+#define SURFACE_SIZE_MULTIPLIER (5.0f * 4.0f)
 #define BACKGROUND_RETENTION_PERCENTAGE (0.5f)
 
 CacheManager::CacheManager(const DisplayInfo& display)
diff --git a/libs/hwui/utils/LinearAllocator.h b/libs/hwui/utils/LinearAllocator.h
index 9c4a1be..539e654 100644
--- a/libs/hwui/utils/LinearAllocator.h
+++ b/libs/hwui/utils/LinearAllocator.h
@@ -115,6 +115,7 @@
      * wasted)
      */
     size_t usedSize() const { return mTotalAllocated - mWastedSpace; }
+    size_t allocatedSize() const { return mTotalAllocated; }
 
 private:
     LinearAllocator(const LinearAllocator& other);
diff --git a/location/java/android/location/LocationManager.java b/location/java/android/location/LocationManager.java
index 68480ce..90e29df 100644
--- a/location/java/android/location/LocationManager.java
+++ b/location/java/android/location/LocationManager.java
@@ -145,7 +145,7 @@
      * Key used for an extra holding a boolean enabled/disabled status value when a provider
      * enabled/disabled event is broadcast using a PendingIntent.
      *
-     * @see #requestLocationUpdates(String, long, long, PendingIntent)
+     * @see #requestLocationUpdates(String, long, float, PendingIntent)
      */
     public static final String KEY_PROVIDER_ENABLED = "providerEnabled";
 
@@ -153,7 +153,7 @@
      * Key used for an extra holding a {@link Location} value when a location change is broadcast
      * using a PendingIntent.
      *
-     * @see #requestLocationUpdates(String, long, long, PendingIntent)
+     * @see #requestLocationUpdates(String, long, float, PendingIntent)
      */
     public static final String KEY_LOCATION_CHANGED = "location";
 
@@ -940,9 +940,8 @@
             @Nullable LocationRequest locationRequest,
             @NonNull LocationListener listener,
             @Nullable Looper looper) {
-        requestLocationUpdates(locationRequest,
-                new LocationListenerTransport(looper == null ? new Handler() : new Handler(looper),
-                        listener));
+        Handler handler = looper == null ? new Handler() : new Handler(looper);
+        requestLocationUpdates(locationRequest, new HandlerExecutor(handler), listener);
     }
 
     /**
@@ -969,7 +968,31 @@
             @Nullable LocationRequest locationRequest,
             @NonNull @CallbackExecutor Executor executor,
             @NonNull LocationListener listener) {
-        requestLocationUpdates(locationRequest, new LocationListenerTransport(executor, listener));
+        synchronized (mListeners) {
+            LocationListenerTransport transport = mListeners.get(listener);
+            if (transport != null) {
+                transport.unregister();
+            } else {
+                transport = new LocationListenerTransport(listener);
+                mListeners.put(listener, transport);
+            }
+            transport.register(executor);
+
+            boolean registered = false;
+            try {
+                mService.requestLocationUpdates(locationRequest, transport, null,
+                        mContext.getPackageName());
+                registered = true;
+            } catch (RemoteException e) {
+                throw e.rethrowFromSystemServer();
+            } finally {
+                if (!registered) {
+                    // allow gc after exception
+                    transport.unregister();
+                    mListeners.remove(listener);
+                }
+            }
+        }
     }
 
     /**
@@ -1009,23 +1032,6 @@
         }
     }
 
-    private void requestLocationUpdates(@Nullable LocationRequest request,
-            @NonNull LocationListenerTransport transport) {
-        synchronized (mListeners) {
-            LocationListenerTransport oldTransport = mListeners.put(transport.getKey(), transport);
-            if (oldTransport != null) {
-                oldTransport.unregisterListener();
-            }
-
-            try {
-                mService.requestLocationUpdates(request, transport, null,
-                        mContext.getPackageName());
-            } catch (RemoteException e) {
-                throw e.rethrowFromSystemServer();
-            }
-        }
-    }
-
     /**
      * Set the last known location with a new location.
      *
@@ -1079,7 +1085,7 @@
             if (transport == null) {
                 return;
             }
-            transport.unregisterListener();
+            transport.unregister();
 
             try {
                 mService.removeUpdates(transport, null, mContext.getPackageName());
@@ -1250,44 +1256,46 @@
     }
 
     /**
-     * Creates a mock location provider and adds it to the set of active providers.
+     * Creates a test location provider and adds it to the set of active providers. This provider
+     * will replace any provider with the same name that exists prior to this call.
      *
-     * @param name the provider name
+     * @param provider the provider name
      *
+     * @throws IllegalArgumentException if provider is null
      * @throws SecurityException if {@link android.app.AppOpsManager#OPSTR_MOCK_LOCATION
      * mock location app op} is not set to {@link android.app.AppOpsManager#MODE_ALLOWED
      * allowed} for your app.
-     * @throws IllegalArgumentException if a provider with the given name already exists
      */
     public void addTestProvider(
-            @NonNull String name, boolean requiresNetwork, boolean requiresSatellite,
+            @NonNull String provider, boolean requiresNetwork, boolean requiresSatellite,
             boolean requiresCell, boolean hasMonetaryCost, boolean supportsAltitude,
             boolean supportsSpeed, boolean supportsBearing, int powerRequirement, int accuracy) {
+        Preconditions.checkArgument(provider != null, "invalid null provider");
+
         ProviderProperties properties = new ProviderProperties(requiresNetwork,
                 requiresSatellite, requiresCell, hasMonetaryCost, supportsAltitude, supportsSpeed,
                 supportsBearing, powerRequirement, accuracy);
-        if (name.matches(LocationProvider.BAD_CHARS_REGEX)) {
-            throw new IllegalArgumentException("provider name contains illegal character: " + name);
-        }
-
         try {
-            mService.addTestProvider(name, properties, mContext.getOpPackageName());
+            mService.addTestProvider(provider, properties, mContext.getOpPackageName());
         } catch (RemoteException e) {
             throw e.rethrowFromSystemServer();
         }
     }
 
     /**
-     * Removes the mock location provider with the given name.
+     * Removes the test location provider with the given name or does nothing if no such test
+     * location provider exists.
      *
      * @param provider the provider name
      *
+     * @throws IllegalArgumentException if provider is null
      * @throws SecurityException if {@link android.app.AppOpsManager#OPSTR_MOCK_LOCATION
      * mock location app op} is not set to {@link android.app.AppOpsManager#MODE_ALLOWED
      * allowed} for your app.
-     * @throws IllegalArgumentException if no provider with the given name exists
      */
     public void removeTestProvider(@NonNull String provider) {
+        Preconditions.checkArgument(provider != null, "invalid null provider");
+
         try {
             mService.removeTestProvider(provider, mContext.getOpPackageName());
         } catch (RemoteException e) {
@@ -1296,60 +1304,53 @@
     }
 
     /**
-     * Sets a mock location for the given provider.
-     * <p>This location will be used in place of any actual location from the provider.
-     * The location object must have a minimum number of fields set to be
-     * considered a valid LocationProvider Location, as per documentation
-     * on {@link Location} class.
+     * Sets a new location for the given test provider. This location will be identiable as a mock
+     * location to all clients via {@link Location#isFromMockProvider()}.
+     *
+     * <p>The location object must have a minimum number of fields set to be considered valid, as
+     * per documentation on {@link Location} class.
      *
      * @param provider the provider name
-     * @param loc the mock location
+     * @param location the mock location
      *
      * @throws SecurityException if {@link android.app.AppOpsManager#OPSTR_MOCK_LOCATION
      * mock location app op} is not set to {@link android.app.AppOpsManager#MODE_ALLOWED
      * allowed} for your app.
-     * @throws IllegalArgumentException if no provider with the given name exists
-     * @throws IllegalArgumentException if the location is incomplete
+     * @throws IllegalArgumentException if the provider is null or not a test provider
+     * @throws IllegalArgumentException if the location is null or incomplete
      */
-    public void setTestProviderLocation(@NonNull String provider, @NonNull Location loc) {
-        if (!loc.isComplete()) {
+    public void setTestProviderLocation(@NonNull String provider, @NonNull Location location) {
+        Preconditions.checkArgument(provider != null, "invalid null provider");
+        Preconditions.checkArgument(location != null, "invalid null location");
+
+        if (!location.isComplete()) {
             IllegalArgumentException e = new IllegalArgumentException(
-                    "Incomplete location object, missing timestamp or accuracy? " + loc);
+                    "Incomplete location object, missing timestamp or accuracy? " + location);
             if (mContext.getApplicationInfo().targetSdkVersion <= Build.VERSION_CODES.JELLY_BEAN) {
-                // just log on old platform (for backwards compatibility)
                 Log.w(TAG, e);
-                loc.makeComplete();
+                location.makeComplete();
             } else {
-                // really throw it!
                 throw e;
             }
         }
 
         try {
-            mService.setTestProviderLocation(provider, loc, mContext.getOpPackageName());
+            mService.setTestProviderLocation(provider, location, mContext.getOpPackageName());
         } catch (RemoteException e) {
             throw e.rethrowFromSystemServer();
         }
     }
 
     /**
-     * Removes any mock location associated with the given provider.
+     * Does nothing.
      *
-     * @param provider the provider name
-     *
-     * @throws SecurityException if {@link android.app.AppOpsManager#OPSTR_MOCK_LOCATION
-     * mock location app op} is not set to {@link android.app.AppOpsManager#MODE_ALLOWED
-     * allowed} for your app.
-     * @throws IllegalArgumentException if no provider with the given name exists
-     *
-     * @deprecated This function has always been a no-op, and may be removed in the future.
+     * @deprecated This method has always been a no-op, and may be removed in the future.
      */
     @Deprecated
     public void clearTestProviderLocation(@NonNull String provider) {}
 
     /**
-     * Sets a mock enabled value for the given provider.  This value will be used in place
-     * of any actual value from the provider.
+     * Sets the given test provider to be enabled or disabled.
      *
      * @param provider the provider name
      * @param enabled the mock enabled value
@@ -1357,9 +1358,11 @@
      * @throws SecurityException if {@link android.app.AppOpsManager#OPSTR_MOCK_LOCATION
      * mock location app op} is not set to {@link android.app.AppOpsManager#MODE_ALLOWED
      * allowed} for your app.
-     * @throws IllegalArgumentException if no provider with the given name exists
+     * @throws IllegalArgumentException if provider is null or not a test provider
      */
     public void setTestProviderEnabled(@NonNull String provider, boolean enabled) {
+        Preconditions.checkArgument(provider != null, "invalid null provider");
+
         try {
             mService.setTestProviderEnabled(provider, enabled, mContext.getOpPackageName());
         } catch (RemoteException e) {
@@ -1368,14 +1371,8 @@
     }
 
     /**
-     * Removes any mock enabled value associated with the given provider.
-     *
-     * @param provider the provider name
-     *
-     * @throws SecurityException if {@link android.app.AppOpsManager#OPSTR_MOCK_LOCATION
-     * mock location app op} is not set to {@link android.app.AppOpsManager#MODE_ALLOWED
-     * allowed} for your app.
-     * @throws IllegalArgumentException if no provider with the given name exists
+     * Equivalent to calling {@link #setTestProviderEnabled(String, boolean)} to disable a test
+     * provider.
      *
      * @deprecated Use {@link #setTestProviderEnabled(String, boolean)} instead.
      */
@@ -2237,49 +2234,45 @@
 
     private class LocationListenerTransport extends ILocationListener.Stub {
 
-        private final Executor mExecutor;
-        @Nullable private volatile LocationListener mListener;
+        private final LocationListener mListener;
+        @Nullable private volatile Executor mExecutor = null;
 
-        private LocationListenerTransport(@NonNull Handler handler,
-                @NonNull LocationListener listener) {
-            Preconditions.checkArgument(handler != null, "invalid null handler");
+        private LocationListenerTransport(@NonNull LocationListener listener) {
             Preconditions.checkArgument(listener != null, "invalid null listener");
-
-            mExecutor = new HandlerExecutor(handler);
             mListener = listener;
         }
 
-        private LocationListenerTransport(@NonNull Executor executor,
-                @NonNull LocationListener listener) {
-            Preconditions.checkArgument(executor != null, "invalid null executor");
-            Preconditions.checkArgument(listener != null, "invalid null listener");
-
-            mExecutor = executor;
-            mListener = listener;
-        }
-
-        private LocationListener getKey() {
+        public LocationListener getKey() {
             return mListener;
         }
 
-        private void unregisterListener() {
-            mListener = null;
+        public void register(@NonNull Executor executor) {
+            Preconditions.checkArgument(executor != null, "invalid null executor");
+            mExecutor = executor;
+        }
+
+        public void unregister() {
+            mExecutor = null;
         }
 
         @Override
         public void onLocationChanged(Location location) {
+            Executor currentExecutor = mExecutor;
+            if (currentExecutor == null) {
+                return;
+            }
+
             try {
-                mExecutor.execute(() -> {
+                currentExecutor.execute(() -> {
                     try {
-                        LocationListener listener = mListener;
-                        if (listener == null) {
+                        if (currentExecutor != mExecutor) {
                             return;
                         }
 
                         // we may be under the binder identity if a direct executor is used
                         long identity = Binder.clearCallingIdentity();
                         try {
-                            listener.onLocationChanged(location);
+                            mListener.onLocationChanged(location);
                         } finally {
                             Binder.restoreCallingIdentity(identity);
                         }
@@ -2295,18 +2288,22 @@
 
         @Override
         public void onStatusChanged(String provider, int status, Bundle extras) {
+            Executor currentExecutor = mExecutor;
+            if (currentExecutor == null) {
+                return;
+            }
+
             try {
-                mExecutor.execute(() -> {
+                currentExecutor.execute(() -> {
                     try {
-                        LocationListener listener = mListener;
-                        if (listener == null) {
+                        if (currentExecutor != mExecutor) {
                             return;
                         }
 
                         // we may be under the binder identity if a direct executor is used
                         long identity = Binder.clearCallingIdentity();
                         try {
-                            listener.onStatusChanged(provider, status, extras);
+                            mListener.onStatusChanged(provider, status, extras);
                         } finally {
                             Binder.restoreCallingIdentity(identity);
                         }
@@ -2322,18 +2319,22 @@
 
         @Override
         public void onProviderEnabled(String provider) {
+            Executor currentExecutor = mExecutor;
+            if (currentExecutor == null) {
+                return;
+            }
+
             try {
-                mExecutor.execute(() -> {
+                currentExecutor.execute(() -> {
                     try {
-                        LocationListener listener = mListener;
-                        if (listener == null) {
+                        if (currentExecutor != mExecutor) {
                             return;
                         }
 
                         // we may be under the binder identity if a direct executor is used
                         long identity = Binder.clearCallingIdentity();
                         try {
-                            listener.onProviderEnabled(provider);
+                            mListener.onProviderEnabled(provider);
                         } finally {
                             Binder.restoreCallingIdentity(identity);
                         }
@@ -2349,18 +2350,22 @@
 
         @Override
         public void onProviderDisabled(String provider) {
+            Executor currentExecutor = mExecutor;
+            if (currentExecutor == null) {
+                return;
+            }
+
             try {
-                mExecutor.execute(() -> {
+                currentExecutor.execute(() -> {
                     try {
-                        LocationListener listener = mListener;
-                        if (listener == null) {
+                        if (currentExecutor != mExecutor) {
                             return;
                         }
 
                         // we may be under the binder identity if a direct executor is used
                         long identity = Binder.clearCallingIdentity();
                         try {
-                            listener.onProviderDisabled(provider);
+                            mListener.onProviderDisabled(provider);
                         } finally {
                             Binder.restoreCallingIdentity(identity);
                         }
diff --git a/location/java/android/location/LocationProvider.java b/location/java/android/location/LocationProvider.java
index b69a9d7..52a03b6 100644
--- a/location/java/android/location/LocationProvider.java
+++ b/location/java/android/location/LocationProvider.java
@@ -53,28 +53,10 @@
     @Deprecated
     public static final int AVAILABLE = 2;
 
-    /**
-     * A regular expression matching characters that may not appear
-     * in the name of a LocationProvider
-     * @hide
-     */
-    public static final String BAD_CHARS_REGEX = "[^a-zA-Z0-9]";
-
     private final String mName;
     private final ProviderProperties mProperties;
 
-    /**
-     * Constructs a LocationProvider with the given name.   Provider names must
-     * consist only of the characters [a-zA-Z0-9].
-     *
-     * @throws IllegalArgumentException if name contains an illegal character
-     *
-     * @hide
-     */
-    public LocationProvider(String name, ProviderProperties properties) {
-        if (name.matches(BAD_CHARS_REGEX)) {
-            throw new IllegalArgumentException("provider name contains illegal character: " + name);
-        }
+    LocationProvider(String name, ProviderProperties properties) {
         mName = name;
         mProperties = properties;
     }
diff --git a/media/java/android/media/ExifInterface.java b/media/java/android/media/ExifInterface.java
index 53babcb..5341d07 100644
--- a/media/java/android/media/ExifInterface.java
+++ b/media/java/android/media/ExifInterface.java
@@ -1357,6 +1357,7 @@
     private AssetManager.AssetInputStream mAssetInputStream;
     private boolean mIsInputStream;
     private int mMimeType;
+    private boolean mIsStandalone;
     @UnsupportedAppUsage
     private final HashMap[] mAttributes = new HashMap[EXIF_TAGS.length];
     private Set<Integer> mHandledIfdOffsets = new HashSet<>(EXIF_TAGS.length);
@@ -1411,6 +1412,7 @@
         if (fileDescriptor == null) {
             throw new NullPointerException("fileDescriptor cannot be null");
         }
+
         mAssetInputStream = null;
         mFilename = null;
         // When FileDescriptor is duplicated and set to FileInputStream, ownership needs to be
@@ -1442,26 +1444,61 @@
 
     /**
      * Reads Exif tags from the specified image input stream. Attribute mutation is not supported
-     * for input streams. The given input stream will proceed its current position. Developers
+     * for input streams. The given input stream will proceed from its current position. Developers
      * should close the input stream after use.
      */
     public ExifInterface(@NonNull InputStream inputStream) throws IOException {
+        this(inputStream, false);
+    }
+
+    /**
+     * Reads Exif tags from the specified standalone input stream. Standalone data refers to Exif
+     * data that exists by itself and is not contained in a file format such as jpeg or png.
+     * The format of the standalone data must follow the below structure:
+     *     Exif Identifier Code ("Exif\0\0") + TIFF header + IFD data
+     * See JEITA CP-3451C Section 4.5.2 and 4.5.4 specifications for more details.
+     * <p>
+     * Attribute mutation is not supported for this constructor. The given input stream will proceed
+     * from its current position. Developers should close the input stream after use. This
+     * constructor is not intended to be used with an input stream that performs any networking
+     * operations.
+     *
+     * @throws IOException if the data does not follow the aforementioned structure.
+     */
+    @NonNull
+    public static ExifInterface fromStandalone(@NonNull InputStream inputStream)
+            throws IOException {
+        if (isStandalone(inputStream)) {
+            return new ExifInterface(inputStream, true);
+        }
+        throw new IOException("Given data does not follow the structure of a standalone exif "
+                + "data.");
+    }
+
+    private ExifInterface(@NonNull InputStream inputStream, boolean isFromStandalone)
+            throws IOException {
         if (inputStream == null) {
             throw new NullPointerException("inputStream cannot be null");
         }
         mFilename = null;
-        if (inputStream instanceof AssetManager.AssetInputStream) {
-            mAssetInputStream = (AssetManager.AssetInputStream) inputStream;
-            mSeekableFileDescriptor = null;
-        } else if (inputStream instanceof FileInputStream
-                && isSeekableFD(((FileInputStream) inputStream).getFD())) {
+
+        if (isFromStandalone) {
+            mIsStandalone = true;
             mAssetInputStream = null;
-            mSeekableFileDescriptor = ((FileInputStream) inputStream).getFD();
+            mSeekableFileDescriptor = null;
         } else {
-            mAssetInputStream = null;
-            mSeekableFileDescriptor = null;
+            if (inputStream instanceof AssetManager.AssetInputStream) {
+                mAssetInputStream = (AssetManager.AssetInputStream) inputStream;
+                mSeekableFileDescriptor = null;
+            } else if (inputStream instanceof FileInputStream
+                    && (isSeekableFD(((FileInputStream) inputStream).getFD()))) {
+                mAssetInputStream = null;
+                mSeekableFileDescriptor = ((FileInputStream) inputStream).getFD();
+            } else {
+                mAssetInputStream = null;
+                mSeekableFileDescriptor = null;
+            }
         }
-        mIsInputStream = true;
         loadAttributes(inputStream);
     }
 
@@ -1798,51 +1835,57 @@
             }
 
             // Check file type
-            in = new BufferedInputStream(in, SIGNATURE_CHECK_SIZE);
-            mMimeType = getMimeType((BufferedInputStream) in);
+            if (!mIsStandalone) {
+                in = new BufferedInputStream(in, SIGNATURE_CHECK_SIZE);
+                mMimeType = getMimeType((BufferedInputStream) in);
+            }
 
             // Create byte-ordered input stream
             ByteOrderedDataInputStream inputStream = new ByteOrderedDataInputStream(in);
 
-            switch (mMimeType) {
-                case IMAGE_TYPE_JPEG: {
-                    getJpegAttributes(inputStream, 0, IFD_TYPE_PRIMARY); // 0 is offset
-                    break;
+            if (!mIsStandalone) {
+                switch (mMimeType) {
+                    case IMAGE_TYPE_JPEG: {
+                        getJpegAttributes(inputStream, 0, IFD_TYPE_PRIMARY); // 0 is offset
+                        break;
+                    }
+                    case IMAGE_TYPE_RAF: {
+                        getRafAttributes(inputStream);
+                        break;
+                    }
+                    case IMAGE_TYPE_HEIF: {
+                        getHeifAttributes(inputStream);
+                        break;
+                    }
+                    case IMAGE_TYPE_ORF: {
+                        getOrfAttributes(inputStream);
+                        break;
+                    }
+                    case IMAGE_TYPE_RW2: {
+                        getRw2Attributes(inputStream);
+                        break;
+                    }
+                    case IMAGE_TYPE_PNG: {
+                        getPngAttributes(inputStream);
+                        break;
+                    }
+                    case IMAGE_TYPE_ARW:
+                    case IMAGE_TYPE_CR2:
+                    case IMAGE_TYPE_DNG:
+                    case IMAGE_TYPE_NEF:
+                    case IMAGE_TYPE_NRW:
+                    case IMAGE_TYPE_PEF:
+                    case IMAGE_TYPE_SRW:
+                    case IMAGE_TYPE_UNKNOWN: {
+                        getRawAttributes(inputStream);
+                        break;
+                    }
+                    default: {
+                        break;
+                    }
                 }
-                case IMAGE_TYPE_RAF: {
-                    getRafAttributes(inputStream);
-                    break;
-                }
-                case IMAGE_TYPE_HEIF: {
-                    getHeifAttributes(inputStream);
-                    break;
-                }
-                case IMAGE_TYPE_ORF: {
-                    getOrfAttributes(inputStream);
-                    break;
-                }
-                case IMAGE_TYPE_RW2: {
-                    getRw2Attributes(inputStream);
-                    break;
-                }
-                case IMAGE_TYPE_PNG: {
-                    getPngAttributes(inputStream);
-                    break;
-                }
-                case IMAGE_TYPE_ARW:
-                case IMAGE_TYPE_CR2:
-                case IMAGE_TYPE_DNG:
-                case IMAGE_TYPE_NEF:
-                case IMAGE_TYPE_NRW:
-                case IMAGE_TYPE_PEF:
-                case IMAGE_TYPE_SRW:
-                case IMAGE_TYPE_UNKNOWN: {
-                    getRawAttributes(inputStream);
-                    break;
-                }
-                default: {
-                    break;
-                }
+            } else {
+                getStandaloneAttributes(inputStream);
             }
             // Set thumbnail image offset and length
             setThumbnailData(inputStream);
@@ -2124,6 +2167,9 @@
         }
 
         if (mHasThumbnail) {
+            if (mIsStandalone) {
+                return new long[] { mThumbnailOffset + mExifOffset, mThumbnailLength };
+            }
             return new long[] { mThumbnailOffset, mThumbnailLength };
         } else {
             return null;
@@ -2368,6 +2414,7 @@
 
     // Checks the type of image file
     private int getMimeType(BufferedInputStream in) throws IOException {
+        // TODO (b/142218289): Need to handle case where input stream does not support mark
         in.mark(SIGNATURE_CHECK_SIZE);
         byte[] signatureCheckBytes = new byte[SIGNATURE_CHECK_SIZE];
         in.read(signatureCheckBytes);
@@ -2562,6 +2609,18 @@
         return true;
     }
 
+    private static boolean isStandalone(InputStream inputStream) throws IOException {
+        byte[] signatureCheckBytes = new byte[IDENTIFIER_EXIF_APP1.length];
+        inputStream.read(signatureCheckBytes);
+
+        for (int i = 0; i < IDENTIFIER_EXIF_APP1.length; i++) {
+            if (signatureCheckBytes[i] != IDENTIFIER_EXIF_APP1[i]) {
+                return false;
+            }
+        }
+        return true;
+    }
+
     /**
      * Loads EXIF attributes from a JPEG input stream.
      *
@@ -2633,7 +2692,6 @@
                         final long offset = start + IDENTIFIER_EXIF_APP1.length;
                         final byte[] value = Arrays.copyOfRange(bytes,
                                 IDENTIFIER_EXIF_APP1.length, bytes.length);
-
                         readExifSegment(value, imageType);
 
                         // Save offset values for handleThumbnailFromJfif() function
@@ -2953,6 +3011,16 @@
         }
     }
 
+    private void getStandaloneAttributes(ByteOrderedDataInputStream in) throws IOException {
+        // TODO: Need to handle potential OutOfMemoryError
+        byte[] data = new byte[in.available()];
+        in.readFully(data);
+        readExifSegment(data, IFD_TYPE_PRIMARY);
+
+        // Save offset values for handleThumbnailFromJfif() function
+        mExifOffset = IDENTIFIER_EXIF_APP1.length;
+    }
+
     /**
      * ORF files contains a primary image data and a MakerNote data that contains preview/thumbnail
      * images. Both data takes the form of IFDs and can therefore be read with the
@@ -3606,8 +3674,6 @@
             int thumbnailOffset = jpegInterchangeFormatAttribute.getIntValue(mExifByteOrder);
             int thumbnailLength = jpegInterchangeFormatLengthAttribute.getIntValue(mExifByteOrder);
 
-            // The following code limits the size of thumbnail size not to overflow EXIF data area.
-            thumbnailLength = Math.min(thumbnailLength, in.getLength() - thumbnailOffset);
             if (mMimeType == IMAGE_TYPE_JPEG || mMimeType == IMAGE_TYPE_RAF
                     || mMimeType == IMAGE_TYPE_RW2) {
                 thumbnailOffset += mExifOffset;
@@ -3615,6 +3681,9 @@
                 // Update offset value since RAF files have IFD data preceding MakerNote data.
                 thumbnailOffset += mOrfMakerNoteOffset;
             }
+            // The following code limits the size of thumbnail size not to overflow EXIF data area.
+            thumbnailLength = Math.min(thumbnailLength, in.getLength() - thumbnailOffset);
+
             if (DEBUG) {
                 Log.d(TAG, "Setting thumbnail attributes with offset: " + thumbnailOffset
                         + ", length: " + thumbnailLength);
@@ -4123,6 +4192,7 @@
             mDataInputStream = new DataInputStream(in);
             mLength = mDataInputStream.available();
             mPosition = 0;
+            // TODO (b/142218289): Need to handle case where input stream does not support mark
             mDataInputStream.mark(mLength);
         }
 
@@ -4138,6 +4208,7 @@
             if (mPosition > byteCount) {
                 mPosition = 0;
                 mDataInputStream.reset();
+                // TODO (b/142218289): Need to handle case where input stream does not support mark
                 mDataInputStream.mark(mLength);
             } else {
                 byteCount -= mPosition;
diff --git a/media/java/android/media/IMediaRouterService.aidl b/media/java/android/media/IMediaRouterService.aidl
index 1b713b6..81213b9 100644
--- a/media/java/android/media/IMediaRouterService.aidl
+++ b/media/java/android/media/IMediaRouterService.aidl
@@ -40,6 +40,7 @@
     void setSelectedRoute(IMediaRouterClient client, String routeId, boolean explicit);
     void requestSetVolume(IMediaRouterClient client, String routeId, int volume);
     void requestUpdateVolume(IMediaRouterClient client, String routeId, int direction);
+    void setControlCategories(IMediaRouterClient client, in List<String> categories);
 
     // Methods for media router 2
     void registerClient2(IMediaRouter2Client client, String packageName);
@@ -52,7 +53,7 @@
      * @param route the route to be selected
      */
     void selectRoute2(IMediaRouter2Client client, in @nullable MediaRoute2Info route);
-    void setControlCategories(IMediaRouter2Client client, in List<String> categories);
+    void setControlCategories2(IMediaRouter2Client client, in List<String> categories);
 
     void registerManager(IMediaRouter2Manager manager, String packageName);
     void unregisterManager(IMediaRouter2Manager manager);
diff --git a/media/java/android/media/MediaCodec.java b/media/java/android/media/MediaCodec.java
index 510ee44..b7a9ffe 100644
--- a/media/java/android/media/MediaCodec.java
+++ b/media/java/android/media/MediaCodec.java
@@ -649,7 +649,7 @@
  are not consumed by the Surface in a timely manner). Or it may be configured to not drop excessive
  frames. In the latter mode if the Surface is not consuming output frames fast enough, it will
  eventually block the decoder. Prior to {@link android.os.Build.VERSION_CODES#Q} the exact behavior
- was undefined, with the exception that View surfaces (SuerfaceView or TextureView) always dropped
+ was undefined, with the exception that View surfaces (SurfaceView or TextureView) always dropped
  excessive frames. Since {@link android.os.Build.VERSION_CODES#Q} the default behavior is to drop
  excessive frames. Applications can opt out of this behavior for non-View surfaces (such as
  ImageReader or SurfaceTexture) by targeting SDK {@link android.os.Build.VERSION_CODES#Q} and
@@ -3513,6 +3513,19 @@
     public static final String PARAMETER_KEY_HDR10_PLUS_INFO = MediaFormat.KEY_HDR10_PLUS_INFO;
 
     /**
+     * Enable/disable low latency decoding mode.
+     * When enabled, the decoder doesn't hold input and output data more than
+     * required by the codec standards.
+     * The value is an Integer object containing the value 1 to enable
+     * or the value 0 to disable.
+     *
+     * @see #setParameters(Bundle)
+     * @see MediaFormat#KEY_LOW_LATENCY
+     */
+    public static final String PARAMETER_KEY_LOW_LATENCY =
+            MediaFormat.KEY_LOW_LATENCY;
+
+    /**
      * Communicate additional parameter changes to the component instance.
      * <b>Note:</b> Some of these parameter changes may silently fail to apply.
      *
diff --git a/media/java/android/media/MediaCodecInfo.java b/media/java/android/media/MediaCodecInfo.java
index f304f7c..26e7936 100644
--- a/media/java/android/media/MediaCodecInfo.java
+++ b/media/java/android/media/MediaCodecInfo.java
@@ -559,6 +559,14 @@
         public static final String FEATURE_IntraRefresh = "intra-refresh";
 
         /**
+         * <b>decoder only</b>: codec supports low latency decoding.
+         * If supported, clients can enable the low latency mode for the decoder.
+         * When the mode is enabled, the decoder doesn't hold input and output data more than
+         * required by the codec standards.
+         */
+        public static final String FEATURE_LowLatency = "low-latency";
+
+        /**
          * Query codec feature capabilities.
          * <p>
          * These features are supported to be used by the codec.  These
@@ -587,6 +595,7 @@
             new Feature(FEATURE_FrameParsing,     (1 << 4), false),
             new Feature(FEATURE_MultipleFrames,   (1 << 5), false),
             new Feature(FEATURE_DynamicTimestamp, (1 << 6), false),
+            new Feature(FEATURE_LowLatency,       (1 << 7), true),
         };
 
         private static final Feature[] encoderFeatures = {
diff --git a/media/java/android/media/MediaFile.java b/media/java/android/media/MediaFile.java
index 8887c7c..09221a37 100644
--- a/media/java/android/media/MediaFile.java
+++ b/media/java/android/media/MediaFile.java
@@ -23,7 +23,7 @@
 import android.annotation.UnsupportedAppUsage;
 import android.mtp.MtpConstants;
 
-import libcore.net.MimeMap;
+import libcore.content.type.MimeMap;
 
 import java.util.HashMap;
 
diff --git a/media/java/android/media/MediaFormat.java b/media/java/android/media/MediaFormat.java
index 8b667f7..8080f45 100644
--- a/media/java/android/media/MediaFormat.java
+++ b/media/java/android/media/MediaFormat.java
@@ -211,6 +211,15 @@
     public static final String KEY_MIME = "mime";
 
     /**
+     * An optional key describing the low latency decoding mode. This is an optional parameter
+     * that applies only to decoders. If enabled, the decoder doesn't hold input and output
+     * data more than required by the codec standards.
+     * The associated value is an integer (0 or 1): 1 when low-latency decoding is enabled,
+     * 0 otherwise. The default value is 0.
+     */
+    public static final String KEY_LOW_LATENCY = "low-latency";
+
+    /**
      * A key describing the language of the content, using either ISO 639-1
      * or 639-2/T codes.  The associated value is a string.
      */
diff --git a/media/java/android/media/MediaMetadataRetriever.java b/media/java/android/media/MediaMetadataRetriever.java
index 0346010..7ed431d 100644
--- a/media/java/android/media/MediaMetadataRetriever.java
+++ b/media/java/android/media/MediaMetadataRetriever.java
@@ -227,6 +227,44 @@
     public native String extractMetadata(int keyCode);
 
     /**
+     * This method is similar to {@link #getFrameAtTime(long, int, BitmapParams)}
+     * except that the device will choose the actual {@link Bitmap.Config} to use.
+     *
+     * @param timeUs The time position where the frame will be retrieved.
+     * When retrieving the frame at the given time position, there is no
+     * guarantee that the data source has a frame located at the position.
+     * When this happens, a frame nearby will be returned. If timeUs is
+     * negative, time position and option will ignored, and any frame
+     * that the implementation considers as representative may be returned.
+     *
+     * @param option a hint on how the frame is found. Use
+     * {@link #OPTION_PREVIOUS_SYNC} if one wants to retrieve a sync frame
+     * that has a timestamp earlier than or the same as timeUs. Use
+     * {@link #OPTION_NEXT_SYNC} if one wants to retrieve a sync frame
+     * that has a timestamp later than or the same as timeUs. Use
+     * {@link #OPTION_CLOSEST_SYNC} if one wants to retrieve a sync frame
+     * that has a timestamp closest to or the same as timeUs. Use
+     * {@link #OPTION_CLOSEST} if one wants to retrieve a frame that may
+     * or may not be a sync frame but is closest to or the same as timeUs.
+     * {@link #OPTION_CLOSEST} often has larger performance overhead compared
+     * to the other options if there is no sync frame located at timeUs.
+     *
+     * @return A Bitmap containing a representative video frame, which can be null,
+     *         if such a frame cannot be retrieved. {@link Bitmap#getConfig()} can
+     *         be used to query the actual {@link Bitmap.Config}.
+     *
+     * @see {@link #getFrameAtTime(long, int, BitmapParams)}
+     */
+    public Bitmap getFrameAtTime(long timeUs, @Option int option) {
+        if (option < OPTION_PREVIOUS_SYNC ||
+            option > OPTION_CLOSEST) {
+            throw new IllegalArgumentException("Unsupported option: " + option);
+        }
+
+        return _getFrameAtTime(timeUs, option, -1 /*dst_width*/, -1 /*dst_height*/, null);
+    }
+
+    /**
      * Call this method after setDataSource(). This method finds a
      * representative frame close to the given time position by considering
      * the given option if possible, and returns it as a bitmap.
@@ -255,16 +293,60 @@
      * {@link #OPTION_CLOSEST} often has larger performance overhead compared
      * to the other options if there is no sync frame located at timeUs.
      *
+     * @param params BitmapParams that controls the returned bitmap config
+     *        (such as pixel formats).
+     *
      * @return A Bitmap containing a representative video frame, which
      *         can be null, if such a frame cannot be retrieved.
+     *
+     * @see {@link #getFrameAtTime(long, int)}
      */
-    public Bitmap getFrameAtTime(long timeUs, @Option int option) {
+    public Bitmap getFrameAtTime(
+            long timeUs, @Option int option, @NonNull BitmapParams params) {
         if (option < OPTION_PREVIOUS_SYNC ||
             option > OPTION_CLOSEST) {
             throw new IllegalArgumentException("Unsupported option: " + option);
         }
 
-        return _getFrameAtTime(timeUs, option, -1 /*dst_width*/, -1 /*dst_height*/);
+        return _getFrameAtTime(timeUs, option, -1 /*dst_width*/, -1 /*dst_height*/, params);
+    }
+
+    /**
+     * This method is similar to {@link #getScaledFrameAtTime(long, int, int, int, BitmapParams)}
+     * except that the device will choose the actual {@link Bitmap.Config} to use.
+     *
+     * @param timeUs The time position in microseconds where the frame will be retrieved.
+     * When retrieving the frame at the given time position, there is no
+     * guarantee that the data source has a frame located at the position.
+     * When this happens, a frame nearby will be returned. If timeUs is
+     * negative, time position and option will ignored, and any frame
+     * that the implementation considers as representative may be returned.
+     *
+     * @param option a hint on how the frame is found. Use
+     * {@link #OPTION_PREVIOUS_SYNC} if one wants to retrieve a sync frame
+     * that has a timestamp earlier than or the same as timeUs. Use
+     * {@link #OPTION_NEXT_SYNC} if one wants to retrieve a sync frame
+     * that has a timestamp later than or the same as timeUs. Use
+     * {@link #OPTION_CLOSEST_SYNC} if one wants to retrieve a sync frame
+     * that has a timestamp closest to or the same as timeUs. Use
+     * {@link #OPTION_CLOSEST} if one wants to retrieve a frame that may
+     * or may not be a sync frame but is closest to or the same as timeUs.
+     * {@link #OPTION_CLOSEST} often has larger performance overhead compared
+     * to the other options if there is no sync frame located at timeUs.
+     *
+     * @param dstWidth expected output bitmap width
+     * @param dstHeight expected output bitmap height
+     * @return A Bitmap containing a representative video frame, which can be null,
+     *         if such a frame cannot be retrieved. {@link Bitmap#getConfig()} can
+     *         be used to query the actual {@link Bitmap.Config}.
+     * @throws IllegalArgumentException if passed in invalid option or width by height
+     *         is less than or equal to 0.
+     * @see {@link #getScaledFrameAtTime(long, int, int, int, BitmapParams)}
+     */
+    public Bitmap getScaledFrameAtTime(
+            long timeUs, @Option int option, int dstWidth, int dstHeight) {
+        validate(option, dstWidth, dstHeight);
+        return _getFrameAtTime(timeUs, option, dstWidth, dstHeight, null);
     }
 
     /**
@@ -297,15 +379,23 @@
      *
      * @param dstWidth expected output bitmap width
      * @param dstHeight expected output bitmap height
+     * @param params BitmapParams that controls the returned bitmap config
+     *        (such as pixel formats).
+     *
      * @return A Bitmap of size not larger than dstWidth by dstHeight containing a
      *         scaled video frame, which can be null, if such a frame cannot be retrieved.
      * @throws IllegalArgumentException if passed in invalid option or width by height
      *         is less than or equal to 0.
+     * @see {@link #getScaledFrameAtTime(long, int, int, int)}
      */
-    public Bitmap getScaledFrameAtTime(
-            long timeUs, @Option int option, int dstWidth, int dstHeight) {
-        if (option < OPTION_PREVIOUS_SYNC ||
-            option > OPTION_CLOSEST) {
+    public 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);
+    }
+
+    private void validate(@Option int option, int dstWidth, int dstHeight) {
+        if (option < OPTION_PREVIOUS_SYNC || option > OPTION_CLOSEST) {
             throw new IllegalArgumentException("Unsupported option: " + option);
         }
         if (dstWidth <= 0) {
@@ -314,8 +404,6 @@
         if (dstHeight <= 0) {
             throw new IllegalArgumentException("Invalid height: " + dstHeight);
         }
-
-        return _getFrameAtTime(timeUs, option, dstWidth, dstHeight);
     }
 
     /**
@@ -365,10 +453,12 @@
      * @see #getFrameAtTime(long, int)
      */
     public Bitmap getFrameAtTime() {
-        return _getFrameAtTime(-1, OPTION_CLOSEST_SYNC, -1 /*dst_width*/, -1 /*dst_height*/);
+        return _getFrameAtTime(
+                -1, OPTION_CLOSEST_SYNC, -1 /*dst_width*/, -1 /*dst_height*/, null);
     }
 
-    private native Bitmap _getFrameAtTime(long timeUs, int option, int width, int height);
+    private native Bitmap _getFrameAtTime(
+            long timeUs, int option, int width, int height, @Nullable BitmapParams params);
 
     public static final class BitmapParams {
         private Bitmap.Config inPreferredConfig = Bitmap.Config.ARGB_8888;
@@ -938,8 +1028,6 @@
      * @see MediaFormat#COLOR_STANDARD_BT601_PAL
      * @see MediaFormat#COLOR_STANDARD_BT601_NTSC
      * @see MediaFormat#COLOR_STANDARD_BT2020
-     *
-     * @hide
      */
     public static final int METADATA_KEY_COLOR_STANDARD = 35;
 
@@ -950,8 +1038,6 @@
      * @see MediaFormat#COLOR_TRANSFER_SDR_VIDEO
      * @see MediaFormat#COLOR_TRANSFER_ST2084
      * @see MediaFormat#COLOR_TRANSFER_HLG
-     *
-     * @hide
      */
     public static final int METADATA_KEY_COLOR_TRANSFER = 36;
 
@@ -960,8 +1046,6 @@
      *
      * @see MediaFormat#COLOR_RANGE_LIMITED
      * @see MediaFormat#COLOR_RANGE_FULL
-     *
-     * @hide
      */
     public static final int METADATA_KEY_COLOR_RANGE    = 37;
     // Add more here...
diff --git a/media/java/android/media/MediaRoute2Info.java b/media/java/android/media/MediaRoute2Info.java
index 5dcbb05..abd774d 100644
--- a/media/java/android/media/MediaRoute2Info.java
+++ b/media/java/android/media/MediaRoute2Info.java
@@ -46,6 +46,21 @@
         }
     };
 
+    /**
+     * Playback information indicating the playback volume is fixed, i&#46;e&#46; it cannot be
+     * controlled from this object. An example of fixed playback volume is a remote player,
+     * playing over HDMI where the user prefers to control the volume on the HDMI sink, rather
+     * than attenuate at the source.
+     * @see #getVolumeHandling()
+     */
+    public static final int PLAYBACK_VOLUME_FIXED = 0;
+    /**
+     * Playback information indicating the playback volume is variable and can be controlled
+     * from this object.
+     * @see #getVolumeHandling()
+     */
+    public static final int PLAYBACK_VOLUME_VARIABLE = 1;
+
     @NonNull
     final String mId;
     @Nullable
@@ -58,6 +73,9 @@
     final String mClientPackageName;
     @NonNull
     final List<String> mSupportedCategories;
+    final int mVolume;
+    final int mVolumeMax;
+    final int mVolumeHandling;
     @Nullable
     final Bundle mExtras;
 
@@ -68,6 +86,9 @@
         mDescription = builder.mDescription;
         mClientPackageName = builder.mClientPackageName;
         mSupportedCategories = builder.mSupportedCategories;
+        mVolume = builder.mVolume;
+        mVolumeMax = builder.mVolumeMax;
+        mVolumeHandling = builder.mVolumeHandling;
         mExtras = builder.mExtras;
     }
 
@@ -78,6 +99,9 @@
         mDescription = in.readString();
         mClientPackageName = in.readString();
         mSupportedCategories = in.createStringArrayList();
+        mVolume = in.readInt();
+        mVolumeMax = in.readInt();
+        mVolumeHandling = in.readInt();
         mExtras = in.readBundle();
     }
 
@@ -111,6 +135,9 @@
                 && Objects.equals(mDescription, other.mDescription)
                 && Objects.equals(mClientPackageName, other.mClientPackageName)
                 && Objects.equals(mSupportedCategories, other.mSupportedCategories)
+                && (mVolume == other.mVolume)
+                && (mVolumeMax == other.mVolumeMax)
+                && (mVolumeHandling == other.mVolumeHandling)
                 //TODO: This will be evaluated as false in most cases. Try not to.
                 && Objects.equals(mExtras, other.mExtras);
     }
@@ -162,6 +189,29 @@
         return mSupportedCategories;
     }
 
+    /**
+     * Gets the current volume of the route. This may be invalid if the route is not selected.
+     */
+    public int getVolume() {
+        return mVolume;
+    }
+
+    /**
+     * Gets the maximum volume of the route.
+     */
+    public int getVolumeMax() {
+        return mVolumeMax;
+    }
+
+    /**
+     * Gets information about how volume is handled on the route.
+     *
+     * @return {@link #PLAYBACK_VOLUME_FIXED} or {@link #PLAYBACK_VOLUME_VARIABLE}
+     */
+    public int getVolumeHandling() {
+        return mVolumeHandling;
+    }
+
     @Nullable
     public Bundle getExtras() {
         return mExtras;
@@ -199,6 +249,9 @@
         dest.writeString(mDescription);
         dest.writeString(mClientPackageName);
         dest.writeStringList(mSupportedCategories);
+        dest.writeInt(mVolume);
+        dest.writeInt(mVolumeMax);
+        dest.writeInt(mVolumeHandling);
         dest.writeBundle(mExtras);
     }
 
@@ -209,6 +262,9 @@
                 .append("id=").append(getId())
                 .append(", name=").append(getName())
                 .append(", description=").append(getDescription())
+                .append(", volume=").append(getVolume())
+                .append(", volumeMax=").append(getVolumeMax())
+                .append(", volumeHandling=").append(getVolumeHandling())
                 .append(", providerId=").append(getProviderId())
                 .append(" }");
         return result.toString();
@@ -224,6 +280,9 @@
         String mDescription;
         String mClientPackageName;
         List<String> mSupportedCategories;
+        int mVolume;
+        int mVolumeMax;
+        int mVolumeHandling;
         Bundle mExtras;
 
         public Builder(@NonNull String id, @NonNull String name) {
@@ -251,6 +310,9 @@
             mDescription = routeInfo.mDescription;
             setClientPackageName(routeInfo.mClientPackageName);
             setSupportedCategories(routeInfo.mSupportedCategories);
+            setVolume(routeInfo.mVolume);
+            setVolumeMax(routeInfo.mVolumeMax);
+            setVolumeHandling(routeInfo.mVolumeHandling);
             if (routeInfo.mExtras != null) {
                 mExtras = new Bundle(routeInfo.mExtras);
             }
@@ -345,6 +407,32 @@
         }
 
         /**
+         * Sets the route's current volume, or 0 if unknown.
+         */
+        @NonNull
+        public Builder setVolume(int volume) {
+            mVolume = volume;
+            return this;
+        }
+
+        /**
+         * Sets the route's maximum volume, or 0 if unknown.
+         */
+        @NonNull
+        public Builder setVolumeMax(int volumeMax) {
+            mVolumeMax = volumeMax;
+            return this;
+        }
+
+        /**
+         * Sets the route's volume handling.
+         */
+        @NonNull
+        public Builder setVolumeHandling(int volumeHandling) {
+            mVolumeHandling = volumeHandling;
+            return this;
+        }
+        /**
          * Sets a bundle of extras for the route.
          */
         @NonNull
diff --git a/media/java/android/media/MediaRouter.java b/media/java/android/media/MediaRouter.java
index d72231f..9cb7869 100644
--- a/media/java/android/media/MediaRouter.java
+++ b/media/java/android/media/MediaRouter.java
@@ -49,6 +49,8 @@
 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.HashMap;
 import java.util.List;
 import java.util.Objects;
@@ -82,6 +84,7 @@
 
         final ArrayList<RouteInfo> mRoutes = new ArrayList<RouteInfo>();
         final ArrayList<RouteCategory> mCategories = new ArrayList<RouteCategory>();
+        List<String> mControlCategories = Collections.emptyList();
 
         final RouteCategory mSystemCategory;
 
@@ -358,6 +361,18 @@
             return mDisplayService.getDisplays(DisplayManager.DISPLAY_CATEGORY_PRESENTATION);
         }
 
+        public void setControlCategories(Collection<String> controlCategories) {
+            List<String> newControlCategories = new ArrayList<>(controlCategories);
+            mControlCategories = newControlCategories;
+            if (mClient != null) {
+                try {
+                    mMediaRouterService.setControlCategories(mClient, newControlCategories);
+                } catch (RemoteException ex) {
+                    Log.e(TAG, "Unable to set control categories.", ex);
+                }
+            }
+        }
+
         private void updatePresentationDisplays(int changedDisplayId) {
             final int count = mRoutes.size();
             for (int i = 0; i < count; i++) {
@@ -406,6 +421,7 @@
                 try {
                     Client client = new Client();
                     mMediaRouterService.registerClientAsUser(client, mPackageName, userId);
+                    mMediaRouterService.setControlCategories(client, mControlCategories);
                     mClient = client;
                 } catch (RemoteException ex) {
                     Log.e(TAG, "Unable to register media router client.", ex);
@@ -1302,6 +1318,19 @@
         sStatic.rebindAsUser(userId);
     }
 
+    /**
+     * Sets the control categories of the application.
+     * Routes that support at least one of the given control categories only exists and are handled
+     * by the media router.
+     *
+     * @hide
+     */
+    public void setControlCategories(@NonNull Collection<String> controlCategories) {
+        Objects.requireNonNull(controlCategories, "control categories must not be null");
+
+        sStatic.setControlCategories(controlCategories);
+    }
+
     static void updateRoute(final RouteInfo info) {
         dispatchRouteChanged(info);
     }
diff --git a/media/java/android/media/MediaRouter2.java b/media/java/android/media/MediaRouter2.java
index 8e29e34..ed35ef6 100644
--- a/media/java/android/media/MediaRouter2.java
+++ b/media/java/android/media/MediaRouter2.java
@@ -129,7 +129,7 @@
                 Client client = new Client();
                 try {
                     mMediaRouterService.registerClient2(client, mPackageName);
-                    mMediaRouterService.setControlCategories(client, mControlCategories);
+                    mMediaRouterService.setControlCategories2(client, mControlCategories);
                     mClient = client;
                 } catch (RemoteException ex) {
                     Log.e(TAG, "Unable to register media router.", ex);
@@ -188,7 +188,7 @@
         }
         if (client != null) {
             try {
-                mMediaRouterService.setControlCategories(client, newControlCategories);
+                mMediaRouterService.setControlCategories2(client, newControlCategories);
             } catch (RemoteException ex) {
                 Log.e(TAG, "Unable to set control categories.", ex);
             }
diff --git a/media/java/android/media/ThumbnailUtils.java b/media/java/android/media/ThumbnailUtils.java
index fb581b5..a315c1e 100644
--- a/media/java/android/media/ThumbnailUtils.java
+++ b/media/java/android/media/ThumbnailUtils.java
@@ -139,6 +139,12 @@
 
     /**
      * Create a thumbnail for given audio file.
+     * <p>
+     * This method should only be used for files that you have direct access to;
+     * if you'd like to work with media hosted outside your app, consider using
+     * {@link ContentResolver#loadThumbnail(Uri, Size, CancellationSignal)}
+     * which enables remote providers to efficiently cache and invalidate
+     * thumbnails.
      *
      * @param file The audio file.
      * @param size The desired thumbnail size.
@@ -231,6 +237,12 @@
 
     /**
      * Create a thumbnail for given image file.
+     * <p>
+     * This method should only be used for files that you have direct access to;
+     * if you'd like to work with media hosted outside your app, consider using
+     * {@link ContentResolver#loadThumbnail(Uri, Size, CancellationSignal)}
+     * which enables remote providers to efficiently cache and invalidate
+     * thumbnails.
      *
      * @param file The audio file.
      * @param size The desired thumbnail size.
@@ -334,6 +346,12 @@
 
     /**
      * Create a thumbnail for given video file.
+     * <p>
+     * This method should only be used for files that you have direct access to;
+     * if you'd like to work with media hosted outside your app, consider using
+     * {@link ContentResolver#loadThumbnail(Uri, Size, CancellationSignal)}
+     * which enables remote providers to efficiently cache and invalidate
+     * thumbnails.
      *
      * @param file The video file.
      * @param size The desired thumbnail size.
diff --git a/media/jni/android_media_MediaMetadataRetriever.cpp b/media/jni/android_media_MediaMetadataRetriever.cpp
index 18fd1a0..bc4bceb 100644
--- a/media/jni/android_media_MediaMetadataRetriever.cpp
+++ b/media/jni/android_media_MediaMetadataRetriever.cpp
@@ -350,9 +350,10 @@
     return jBitmap;
 }
 
-static int getColorFormat(JNIEnv *env, jobject options) {
+static int getColorFormat(JNIEnv *env, jobject options,
+        int defaultPreferred = HAL_PIXEL_FORMAT_RGBA_8888) {
     if (options == NULL) {
-        return HAL_PIXEL_FORMAT_RGBA_8888;
+        return defaultPreferred;
     }
 
     ScopedLocalRef<jobject> inConfig(env, env->GetObjectField(options, fields.inPreferredConfig));
@@ -383,7 +384,8 @@
 }
 
 static jobject android_media_MediaMetadataRetriever_getFrameAtTime(
-        JNIEnv *env, jobject thiz, jlong timeUs, jint option, jint dst_width, jint dst_height)
+        JNIEnv *env, jobject thiz, jlong timeUs, jint option,
+        jint dst_width, jint dst_height, jobject params)
 {
     ALOGV("getFrameAtTime: %lld us option: %d dst width: %d heigh: %d",
             (long long)timeUs, option, dst_width, dst_height);
@@ -392,10 +394,13 @@
         jniThrowException(env, "java/lang/IllegalStateException", "No retriever available");
         return NULL;
     }
+    // For getFrameAtTime family of calls, default to HAL_PIXEL_FORMAT_RGB_565
+    // to keep the behavior consistent with older releases
+    int colorFormat = getColorFormat(env, params, HAL_PIXEL_FORMAT_RGB_565);
 
     // Call native method to retrieve a video frame
     VideoFrame *videoFrame = NULL;
-    sp<IMemory> frameMemory = retriever->getFrameAtTime(timeUs, option);
+    sp<IMemory> frameMemory = retriever->getFrameAtTime(timeUs, option, colorFormat);
     // TODO: Using unsecurePointer() has some associated security pitfalls
     //       (see declaration for details).
     //       Either document why it is safe in this case or address the
@@ -408,7 +413,9 @@
         return NULL;
     }
 
-    return getBitmapFromVideoFrame(env, videoFrame, dst_width, dst_height, kRGB_565_SkColorType);
+    SkColorType outColorType = setOutColorType(env, colorFormat, params);
+
+    return getBitmapFromVideoFrame(env, videoFrame, dst_width, dst_height, outColorType);
 }
 
 static jobject android_media_MediaMetadataRetriever_getImageAtIndex(
@@ -739,7 +746,7 @@
                 (void *)android_media_MediaMetadataRetriever_setDataSourceFD},
         {"_setDataSource",   "(Landroid/media/MediaDataSource;)V",
                 (void *)android_media_MediaMetadataRetriever_setDataSourceCallback},
-        {"_getFrameAtTime", "(JIII)Landroid/graphics/Bitmap;",
+        {"_getFrameAtTime", "(JIIILandroid/media/MediaMetadataRetriever$BitmapParams;)Landroid/graphics/Bitmap;",
                 (void *)android_media_MediaMetadataRetriever_getFrameAtTime},
         {
             "_getImageAtIndex",
diff --git a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/unit/MediaFileTest.java b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/unit/MediaFileTest.java
index 38f0175..481f479 100644
--- a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/unit/MediaFileTest.java
+++ b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/unit/MediaFileTest.java
@@ -31,7 +31,7 @@
 
 import androidx.test.runner.AndroidJUnit4;
 
-import libcore.net.MimeMap;
+import libcore.content.type.MimeMap;
 
 import org.junit.Test;
 import org.junit.runner.RunWith;
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 1267aa8..8d39a93 100644
--- a/media/tests/MediaRouteProvider/src/com/android/mediarouteprovider/example/SampleMediaRoute2ProviderService.java
+++ b/media/tests/MediaRouteProvider/src/com/android/mediarouteprovider/example/SampleMediaRoute2ProviderService.java
@@ -36,6 +36,12 @@
     public static final String ROUTE_ID_SPECIAL_CATEGORY = "route_special_category";
     public static final String ROUTE_NAME_SPECIAL_CATEGORY = "Special Category Route";
 
+    public static final int VOLUME_MAX = 100;
+    public static final String ROUTE_ID_FIXED_VOLUME = "route_fixed_volume";
+    public static final String ROUTE_NAME_FIXED_VOLUME = "Fixed Volume Route";
+    public static final String ROUTE_ID_VARIABLE_VOLUME = "route_variable_volume";
+    public static final String ROUTE_NAME_VARIABLE_VOLUME = "Variable Volume Route";
+
     public static final String ACTION_REMOVE_ROUTE =
             "com.android.mediarouteprovider.action_remove_route";
 
@@ -58,9 +64,23 @@
                         .addSupportedCategory(CATEGORY_SAMPLE)
                         .addSupportedCategory(CATEGORY_SPECIAL)
                         .build();
+        MediaRoute2Info fixedVolumeRoute =
+                new MediaRoute2Info.Builder(ROUTE_ID_FIXED_VOLUME, ROUTE_NAME_FIXED_VOLUME)
+                        .addSupportedCategory(CATEGORY_SAMPLE)
+                        .setVolumeHandling(MediaRoute2Info.PLAYBACK_VOLUME_FIXED)
+                        .build();
+        MediaRoute2Info variableVolumeRoute =
+                new MediaRoute2Info.Builder(ROUTE_ID_VARIABLE_VOLUME, ROUTE_NAME_VARIABLE_VOLUME)
+                        .addSupportedCategory(CATEGORY_SAMPLE)
+                        .setVolumeHandling(MediaRoute2Info.PLAYBACK_VOLUME_VARIABLE)
+                        .setVolumeMax(VOLUME_MAX)
+                        .build();
+
         mRoutes.put(route1.getId(), route1);
         mRoutes.put(route2.getId(), route2);
         mRoutes.put(routeSpecial.getId(), routeSpecial);
+        mRoutes.put(fixedVolumeRoute.getId(), fixedVolumeRoute);
+        mRoutes.put(variableVolumeRoute.getId(), variableVolumeRoute);
     }
 
     @Override
diff --git a/media/tests/MediaRouter/src/com/android/mediaroutertest/MediaRouterManagerTest.java b/media/tests/MediaRouter/src/com/android/mediaroutertest/MediaRouterManagerTest.java
index 3abf0a4..da832ac 100644
--- a/media/tests/MediaRouter/src/com/android/mediaroutertest/MediaRouterManagerTest.java
+++ b/media/tests/MediaRouter/src/com/android/mediaroutertest/MediaRouterManagerTest.java
@@ -16,6 +16,9 @@
 
 package com.android.mediaroutertest;
 
+import static android.media.MediaRoute2Info.PLAYBACK_VOLUME_FIXED;
+import static android.media.MediaRoute2Info.PLAYBACK_VOLUME_VARIABLE;
+
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertNotEquals;
 import static org.junit.Assert.assertNotNull;
@@ -27,6 +30,7 @@
 import android.content.Context;
 import android.content.Intent;
 import android.media.MediaRoute2Info;
+import android.media.MediaRouter;
 import android.media.MediaRouter2;
 import android.media.MediaRouter2Manager;
 import android.support.test.InstrumentationRegistry;
@@ -60,6 +64,12 @@
     public static final String ROUTE_ID_SPECIAL_CATEGORY = "route_special_category";
     public static final String ROUTE_NAME_SPECIAL_CATEGORY = "Special Category Route";
 
+    public static final int VOLUME_MAX = 100;
+    public static final String ROUTE_ID_FIXED_VOLUME = "route_fixed_volume";
+    public static final String ROUTE_NAME_FIXED_VOLUME = "Fixed Volume Route";
+    public static final String ROUTE_ID_VARIABLE_VOLUME = "route_variable_volume";
+    public static final String ROUTE_NAME_VARIABLE_VOLUME = "Variable Volume Route";
+
     public static final String ACTION_REMOVE_ROUTE =
             "com.android.mediarouteprovider.action_remove_route";
 
@@ -72,7 +82,8 @@
 
     private Context mContext;
     private MediaRouter2Manager mManager;
-    private MediaRouter2 mRouter;
+    private MediaRouter mRouter;
+    private MediaRouter2 mRouter2;
     private Executor mExecutor;
     private String mPackageName;
 
@@ -89,13 +100,14 @@
     public void setUp() throws Exception {
         mContext = InstrumentationRegistry.getTargetContext();
         mManager = MediaRouter2Manager.getInstance(mContext);
-        mRouter = MediaRouter2.getInstance(mContext);
+        mRouter = (MediaRouter) mContext.getSystemService(Context.MEDIA_ROUTER_SERVICE);
+        mRouter2 = MediaRouter2.getInstance(mContext);
         //TODO: If we need to support thread pool executors, change this to thread pool executor.
         mExecutor = Executors.newSingleThreadExecutor();
         mPackageName = mContext.getPackageName();
     }
 
-    //TODO: Move to a seperate file
+    //TODO: Move to a separate file
     @Test
     public void testMediaRoute2Info() {
         MediaRoute2Info routeInfo1 = new MediaRoute2Info.Builder("id", "name")
@@ -131,12 +143,12 @@
 
         //TODO: Figure out a more proper way to test.
         // (Control requests shouldn't be used in this way.)
-        mRouter.setControlCategories(CONTROL_CATEGORIES_ALL);
-        mRouter.registerCallback(mExecutor, mockRouterCallback);
-        mRouter.sendControlRequest(
+        mRouter2.setControlCategories(CONTROL_CATEGORIES_ALL);
+        mRouter2.registerCallback(mExecutor, mockRouterCallback);
+        mRouter2.sendControlRequest(
                 new MediaRoute2Info.Builder(ROUTE_ID2, ROUTE_NAME2).build(),
                 new Intent(ACTION_REMOVE_ROUTE));
-        mRouter.unregisterCallback(mockRouterCallback);
+        mRouter2.unregisterCallback(mockRouterCallback);
 
         verify(mockCallback, timeout(TIMEOUT_MS)).onRouteRemoved(argThat(
                 (MediaRoute2Info info) ->
@@ -148,15 +160,41 @@
      * Tests if we get proper routes for application that has special control category.
      */
     @Test
+    public void testControlCategoryWithMediaRouter() throws Exception {
+        MediaRouter2Manager.Callback mockCallback = mock(MediaRouter2Manager.Callback.class);
+        mManager.registerCallback(mExecutor, mockCallback);
+
+        MediaRouter.Callback mockRouterCallback = mock(MediaRouter.Callback.class);
+
+        mRouter.setControlCategories(CONTROL_CATEGORIES_SPECIAL);
+        mRouter.addCallback(MediaRouter.ROUTE_TYPE_USER, mockRouterCallback);
+
+        verify(mockCallback, timeout(TIMEOUT_MS))
+                .onRoutesChanged(argThat(routes -> routes.size() > 0));
+
+        Map<String, MediaRoute2Info> routes =
+                createRouteMap(mManager.getAvailableRoutes(mPackageName));
+
+        Assert.assertEquals(1, routes.size());
+        Assert.assertNotNull(routes.get(ROUTE_ID_SPECIAL_CATEGORY));
+
+        mRouter.removeCallback(mockRouterCallback);
+        mManager.unregisterCallback(mockCallback);
+    }
+
+    /**
+     * Tests if we get proper routes for application that has special control category.
+     */
+    @Test
     public void testControlCategory() throws Exception {
         MediaRouter2Manager.Callback mockCallback = mock(MediaRouter2Manager.Callback.class);
         mManager.registerCallback(mExecutor, mockCallback);
 
         MediaRouter2.Callback mockRouterCallback = mock(MediaRouter2.Callback.class);
 
-        mRouter.setControlCategories(CONTROL_CATEGORIES_SPECIAL);
-        mRouter.registerCallback(mExecutor, mockRouterCallback);
-        mRouter.unregisterCallback(mockRouterCallback);
+        mRouter2.setControlCategories(CONTROL_CATEGORIES_SPECIAL);
+        mRouter2.registerCallback(mExecutor, mockRouterCallback);
+        mRouter2.unregisterCallback(mockRouterCallback);
 
         verify(mockCallback, timeout(TIMEOUT_MS))
                 .onRoutesChanged(argThat(routes -> routes.size() > 0));
@@ -177,15 +215,15 @@
     public void testGetRoutes() throws Exception {
         MediaRouter2.Callback mockCallback = mock(MediaRouter2.Callback.class);
 
-        mRouter.setControlCategories(CONTROL_CATEGORIES_SPECIAL);
-        mRouter.registerCallback(mExecutor, mockCallback);
+        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(mRouter.getRoutes());
+        Map<String, MediaRoute2Info> routes = createRouteMap(mRouter2.getRoutes());
         Assert.assertEquals(1, routes.size());
         Assert.assertNotNull(routes.get(ROUTE_ID_SPECIAL_CATEGORY));
 
-        mRouter.unregisterCallback(mockCallback);
+        mRouter2.unregisterCallback(mockCallback);
     }
 
     @Test
@@ -194,8 +232,8 @@
         MediaRouter2Manager.Callback managerCallback = mock(MediaRouter2Manager.Callback.class);
 
         mManager.registerCallback(mExecutor, managerCallback);
-        mRouter.setControlCategories(CONTROL_CATEGORIES_ALL);
-        mRouter.registerCallback(mExecutor, mockRouterCallback);
+        mRouter2.setControlCategories(CONTROL_CATEGORIES_ALL);
+        mRouter2.registerCallback(mExecutor, mockRouterCallback);
 
         verify(managerCallback, timeout(TIMEOUT_MS))
                 .onRoutesChanged(argThat(routes -> routes.size() > 0));
@@ -211,7 +249,7 @@
                 .onRouteAdded(argThat(route -> route.equals(routeToSelect)));
 
         mManager.unregisterCallback(managerCallback);
-        mRouter.unregisterCallback(mockRouterCallback);
+        mRouter2.unregisterCallback(mockRouterCallback);
     }
 
     /**
@@ -223,8 +261,8 @@
         MediaRouter2.Callback routerCallback = mock(MediaRouter2.Callback.class);
 
         mManager.registerCallback(mExecutor, managerCallback);
-        mRouter.setControlCategories(CONTROL_CATEGORIES_ALL);
-        mRouter.registerCallback(mExecutor, routerCallback);
+        mRouter2.setControlCategories(CONTROL_CATEGORIES_ALL);
+        mRouter2.registerCallback(mExecutor, routerCallback);
 
         verify(managerCallback, timeout(TIMEOUT_MS))
                 .onRoutesChanged(argThat(routes -> routes.size() > 0));
@@ -248,10 +286,30 @@
                 .onRouteChanged(argThat(routeInfo -> TextUtils.equals(ROUTE_ID2, routeInfo.getId())
                         && TextUtils.equals(routeInfo.getClientPackageName(), null)));
 
-        mRouter.unregisterCallback(routerCallback);
+        mRouter2.unregisterCallback(routerCallback);
         mManager.unregisterCallback(managerCallback);
     }
 
+    @Test
+    public void testVolumeHandling() {
+        MediaRouter2.Callback mockCallback = mock(MediaRouter2.Callback.class);
+
+        mRouter2.setControlCategories(CONTROL_CATEGORIES_ALL);
+        mRouter2.registerCallback(mExecutor, mockCallback);
+        verify(mockCallback, timeout(TIMEOUT_MS).atLeastOnce())
+                .onRoutesChanged(argThat(routes -> routes.size() > 0));
+        Map<String, MediaRoute2Info> routes = createRouteMap(mRouter2.getRoutes());
+
+        MediaRoute2Info fixedVolumeRoute = routes.get(ROUTE_ID_FIXED_VOLUME);
+        MediaRoute2Info variableVolumeRoute = routes.get(ROUTE_ID_VARIABLE_VOLUME);
+
+        assertEquals(PLAYBACK_VOLUME_FIXED, fixedVolumeRoute.getVolumeHandling());
+        assertEquals(PLAYBACK_VOLUME_VARIABLE, variableVolumeRoute.getVolumeHandling());
+        assertEquals(VOLUME_MAX, variableVolumeRoute.getVolumeMax());
+
+        mRouter2.unregisterCallback(mockCallback);
+    }
+
     // Helper for getting routes easily
     static Map<String, MediaRoute2Info> createRouteMap(List<MediaRoute2Info> routes) {
         Map<String, MediaRoute2Info> routeMap = new HashMap<>();
diff --git a/mime/Android.bp b/mime/Android.bp
index 51290f6..23a8fbf 100644
--- a/mime/Android.bp
+++ b/mime/Android.bp
@@ -43,11 +43,10 @@
 
 // The mimemap-res.jar and mimemap-testing-res.jar genrules produce a .jar that
 // has the resource file in a subdirectory res/ and testres/, respectively.
-// Those paths need to They need to be in different paths because one of them
-// ends up on a bootclasspath jar whereas the other one ends up in a test jar.
-// Bootclasspath resources hide test or application resources under the same
-// path because ClassLoader.getResource(String) consults the parent ClassLoader
-// first.
+// They need to be in different paths because one of them ends up in a
+// bootclasspath jar whereas the other one ends up in a test jar. Bootclasspath
+// resources hide test or application resources under the same path because
+// ClassLoader.getResource(String) consults the parent ClassLoader first.
 //
 // Further notes:
 //  - the "cp" command will flatten any directory paths that occur in $(in),
@@ -61,7 +60,7 @@
     tools: [
         "soong_zip",
     ],
-    srcs: [":mime.types"],
+    srcs: [":mime.types.minimized"],
     out: ["mimemap-res.jar"],
     cmd: "mkdir $(genDir)/res/ && cp $(in) $(genDir)/res/ && $(location soong_zip) -C $(genDir) -o $(out) -D $(genDir)/res/",
 }
@@ -74,42 +73,49 @@
     tools: [
         "soong_zip",
     ],
-    srcs: [":mime.types"],
+    srcs: [":mime.types.minimized"],
     out: ["mimemap-testing-res.jar"],
     cmd: "mkdir $(genDir)/testres/ && cp $(in) $(genDir)/testres/ && $(location soong_zip) -C $(genDir) -o $(out) -D $(genDir)/testres/",
 }
 
-// Combination of all *mime.types resources.
+// Combination of all *mime.types.minimized resources.
 filegroup {
-    name: "mime.types",
+    name: "mime.types.minimized",
     visibility: [
         "//visibility:private",
     ],
     srcs: [
-        ":debian.mime.types",
-        ":android.mime.types",
-        ":vendor.mime.types",
+        ":debian.mime.types.minimized",
+        ":android.mime.types.minimized",
+        ":vendor.mime.types.minimized",
     ],
 }
 
-filegroup {
-    name: "android.mime.types",
+java_genrule {
+    name: "android.mime.types.minimized",
     visibility: [
         "//visibility:private",
     ],
-    path: "java-res/",
+    out: ["android.mime.types"],
     srcs: [
         "java-res/android.mime.types",
     ],
+    //    strip comments            normalize whitepace       drop empty lines
+    cmd: "awk '{gsub(/#.*$$/,\"\"); $$1=$$1; print;}' $(in) | grep ' ' > $(out)",
 }
 
-filegroup {
-    name: "vendor.mime.types",
+// Unlike the other *mime.types files, vendor.mime.types gets '?' prepended to
+// every field so that its mappings will never overwrite earlier mappings by
+// the other resource files. http://b/141842825
+java_genrule {
+    name: "vendor.mime.types.minimized",
     visibility: [
         "//visibility:private",
     ],
-    path: "java-res/",
+    out: ["vendor.mime.types"],
     srcs: [
         "java-res/vendor.mime.types",
     ],
+    //    strip comments            normalize whitepace       drop empty lines   prepend ? to fields that are missing it
+    cmd: "awk '{gsub(/#.*$$/,\"\"); $$1=$$1; print;}' $(in) | grep ' '         | awk '{for(i=1;i<=NF;i++) { sub(/^\\??/, \"?\", $$i); }; print}' > $(out)",
 }
diff --git a/mime/java/android/content/type/DefaultMimeMapFactory.java b/mime/java/android/content/type/DefaultMimeMapFactory.java
index 13039a4..11d20d4 100644
--- a/mime/java/android/content/type/DefaultMimeMapFactory.java
+++ b/mime/java/android/content/type/DefaultMimeMapFactory.java
@@ -16,18 +16,16 @@
 
 package android.content.type;
 
-import libcore.net.MimeMap;
+import libcore.content.type.MimeMap;
 
 import java.io.BufferedReader;
 import java.io.IOException;
 import java.io.InputStream;
 import java.io.InputStreamReader;
 import java.util.ArrayList;
-import java.util.Arrays;
 import java.util.List;
 import java.util.Objects;
 import java.util.function.Function;
-import java.util.regex.Pattern;
 
 /**
  * Creates the framework default {@link MimeMap}, a bidirectional mapping
@@ -53,8 +51,6 @@
         return create(resourceName -> c.getResourceAsStream("/res/" + resourceName));
     }
 
-    private static final Pattern SPLIT_PATTERN = Pattern.compile("\\s+");
-
     /**
      * Creates a {@link MimeMap} instance whose resources are loaded from the
      * InputStreams looked up in {@code resourceSupplier}.
@@ -63,33 +59,43 @@
      */
     public static MimeMap create(Function<String, InputStream> resourceSupplier) {
         MimeMap.Builder builder = MimeMap.builder();
-        parseTypes(builder, true, resourceSupplier, "mime.types");
-        parseTypes(builder, true, resourceSupplier, "android.mime.types");
-        parseTypes(builder, false, resourceSupplier, "vendor.mime.types");
+        // The files loaded here must be in minimized format with lines of the
+        // form "mime/type ext1 ext2 ext3", i.e. no comments, no empty lines, no
+        // leading/trailing whitespace and with a single space between entries on
+        // each line.  See http://b/142267887
+        //
+        // Note: the order here matters - later entries can overwrite earlier ones
+        // (except that vendor.mime.types entries are prefixed with '?' which makes
+        // them never overwrite).
+        parseTypes(builder, resourceSupplier, "debian.mime.types");
+        parseTypes(builder, resourceSupplier, "android.mime.types");
+        parseTypes(builder, resourceSupplier, "vendor.mime.types");
         return builder.build();
     }
 
-    private static void parseTypes(MimeMap.Builder builder, boolean allowOverwrite,
+    private static void parseTypes(MimeMap.Builder builder,
             Function<String, InputStream> resourceSupplier, String resourceName) {
         try (InputStream inputStream = Objects.requireNonNull(resourceSupplier.apply(resourceName));
              BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream))) {
             String line;
+            List<String> specs = new ArrayList<>(10); // re-use for each line
             while ((line = reader.readLine()) != null) {
-                int commentPos = line.indexOf('#');
-                if (commentPos >= 0) {
-                    line = line.substring(0, commentPos);
-                }
-                line = line.trim();
-                if (line.isEmpty()) {
-                    continue;
-                }
-                List<String> specs = Arrays.asList(SPLIT_PATTERN.split(line));
-                if (!allowOverwrite) {
-                    // Pretend that the mimeType and each file extension listed in the line
-                    // carries a "?" prefix, which means that it can add new mappings but
-                    // not modify existing mappings (putIfAbsent() semantics).
-                    specs = ensurePrefix("?", specs);
-                }
+                specs.clear();
+                // Lines are of the form "mimeSpec extSpec extSpec[...]" with a single space
+                // separating them and no leading/trailing spaces and no empty lines.
+                int startIdx = 0;
+                do {
+                    int endIdx = line.indexOf(' ', startIdx);
+                    if (endIdx < 0) {
+                        endIdx = line.length();
+                    }
+                    String spec = line.substring(startIdx, endIdx);
+                    if (spec.isEmpty()) {
+                        throw new IllegalArgumentException("Malformed line: " + line);
+                    }
+                    specs.add(spec);
+                    startIdx = endIdx + 1; // skip over the space
+                } while (startIdx < line.length());
                 builder.put(specs.get(0), specs.subList(1, specs.size()));
             }
         } catch (IOException | RuntimeException e) {
@@ -97,15 +103,4 @@
         }
     }
 
-    private static List<String> ensurePrefix(String prefix, List<String> strings) {
-        List<String> result = new ArrayList<>(strings.size());
-        for (String s : strings) {
-            if (!s.startsWith(prefix)) {
-                s = prefix + s;
-            }
-            result.add(s);
-        }
-        return result;
-    }
-
 }
diff --git a/mms/OWNERS b/mms/OWNERS
new file mode 100644
index 0000000..ba00d5d
--- /dev/null
+++ b/mms/OWNERS
@@ -0,0 +1,14 @@
+set noparent
+
+tgunn@google.com
+breadley@google.com
+hallliu@google.com
+rgreenwalt@google.com
+amitmahajan@google.com
+fionaxu@google.com
+jackyu@google.com
+jminjie@google.com
+satk@google.com
+shuoq@google.com
+refuhoo@google.com
+nazaninb@google.com
diff --git a/telephony/java/android/telephony/MmsManager.java b/mms/java/android/telephony/MmsManager.java
similarity index 100%
rename from telephony/java/android/telephony/MmsManager.java
rename to mms/java/android/telephony/MmsManager.java
diff --git a/telephony/java/com/android/internal/telephony/IMms.aidl b/mms/java/com/android/internal/telephony/IMms.aidl
similarity index 100%
rename from telephony/java/com/android/internal/telephony/IMms.aidl
rename to mms/java/com/android/internal/telephony/IMms.aidl
diff --git a/packages/BackupEncryption/src/com/android/server/backup/encryption/StreamUtils.java b/packages/BackupEncryption/src/com/android/server/backup/encryption/StreamUtils.java
index 91b2926..66be25b 100644
--- a/packages/BackupEncryption/src/com/android/server/backup/encryption/StreamUtils.java
+++ b/packages/BackupEncryption/src/com/android/server/backup/encryption/StreamUtils.java
@@ -18,9 +18,13 @@
 
 import java.io.Closeable;
 import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
 
 /** Utility methods for dealing with Streams */
 public class StreamUtils {
+    private static final int MAX_COPY_BUFFER_SIZE = 1024; // 1k copy buffer size.
+
     /**
      * Close a Closeable and silently ignore any IOExceptions.
      *
@@ -33,4 +37,28 @@
             // Silently ignore
         }
     }
+
+    /**
+     * Copy data from an InputStream to an OutputStream upto a given number of bytes.
+     *
+     * @param in The source InputStream
+     * @param out The destination OutputStream
+     * @param limit The maximum number of bytes to copy
+     * @throws IOException Thrown if there is a problem performing the copy.
+     */
+    public static void copyStream(InputStream in, OutputStream out, int limit) throws IOException {
+        int bufferSize = Math.min(MAX_COPY_BUFFER_SIZE, limit);
+        byte[] buffer = new byte[bufferSize];
+
+        int copied = 0;
+        while (copied < limit) {
+            int maxReadSize = Math.min(bufferSize, limit - copied);
+            int read = in.read(buffer, 0, maxReadSize);
+            if (read < 0) {
+                return; // Reached the stream end before the limit
+            }
+            out.write(buffer, 0, read);
+            copied += read;
+        }
+    }
 }
diff --git a/packages/BackupEncryption/src/com/android/server/backup/encryption/tasks/ClearCryptoStateTask.java b/packages/BackupEncryption/src/com/android/server/backup/encryption/tasks/ClearCryptoStateTask.java
new file mode 100644
index 0000000..8f35db6
--- /dev/null
+++ b/packages/BackupEncryption/src/com/android/server/backup/encryption/tasks/ClearCryptoStateTask.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.server.backup.encryption.tasks;
+
+import android.content.Context;
+import android.util.Slog;
+
+import com.android.server.backup.encryption.CryptoSettings;
+import com.android.server.backup.encryption.chunking.ProtoStore;
+import com.android.server.backup.encryption.storage.BackupEncryptionDb;
+import com.android.server.backup.encryption.storage.EncryptionDbException;
+
+import java.io.IOException;
+
+/**
+ * Task to clear local crypto state.
+ *
+ * <p>Needs to run whenever the user changes their backup account.
+ */
+public class ClearCryptoStateTask {
+    private static final String TAG = "ClearCryptoStateTask";
+
+    private final Context mContext;
+    private final CryptoSettings mCryptoSettings;
+
+    /**
+     * A new instance.
+     *
+     * @param context for finding local storage.
+     * @param cryptoSettings to clear
+     */
+    public ClearCryptoStateTask(Context context, CryptoSettings cryptoSettings) {
+        mContext = context;
+        mCryptoSettings = cryptoSettings;
+    }
+
+    /** Deletes all local state for backup (not restore). */
+    public void run() {
+        Slog.d(TAG, "Clearing local crypto state.");
+        try {
+            BackupEncryptionDb.newInstance(mContext).clear();
+        } catch (EncryptionDbException e) {
+            Slog.e(TAG, "Error clearing encryption database", e);
+        }
+        mCryptoSettings.clearAllSettingsForBackup();
+        try {
+            ProtoStore.createChunkListingStore(mContext).deleteAllProtos();
+        } catch (IOException e) {
+            Slog.e(TAG, "Error clearing chunk listing store", e);
+        }
+        try {
+            ProtoStore.createKeyValueListingStore(mContext).deleteAllProtos();
+        } catch (IOException e) {
+            Slog.e(TAG, "Error clearing key-value store", e);
+        }
+    }
+}
diff --git a/packages/BackupEncryption/src/com/android/server/backup/encryption/tasks/EncryptedFullBackupDataProcessor.java b/packages/BackupEncryption/src/com/android/server/backup/encryption/tasks/EncryptedFullBackupDataProcessor.java
new file mode 100644
index 0000000..0baec8b
--- /dev/null
+++ b/packages/BackupEncryption/src/com/android/server/backup/encryption/tasks/EncryptedFullBackupDataProcessor.java
@@ -0,0 +1,210 @@
+/*
+ * 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.tasks;
+
+import static com.android.internal.util.Preconditions.checkNotNull;
+import static com.android.internal.util.Preconditions.checkState;
+
+import android.annotation.Nullable;
+import android.app.backup.BackupTransport;
+import android.content.Context;
+import android.util.Slog;
+
+import com.android.server.backup.encryption.FullBackupDataProcessor;
+import com.android.server.backup.encryption.StreamUtils;
+import com.android.server.backup.encryption.client.CryptoBackupServer;
+import com.android.server.backup.encryption.keys.RecoverableKeyStoreSecondaryKey;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.PipedInputStream;
+import java.io.PipedOutputStream;
+import java.security.SecureRandom;
+import java.util.Optional;
+import java.util.concurrent.ExecutionException;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Future;
+
+/**
+ * Accepts backup data from a {@link InputStream} and passes it to the encrypted full data backup
+ * path.
+ */
+public class EncryptedFullBackupDataProcessor implements FullBackupDataProcessor {
+
+    private static final String TAG = "EncryptedFullBackupDP";
+
+    private final Context mContext;
+    private final ExecutorService mExecutorService;
+    private final CryptoBackupServer mCryptoBackupServer;
+    private final SecureRandom mSecureRandom;
+    private final RecoverableKeyStoreSecondaryKey mSecondaryKey;
+    private final String mPackageName;
+
+    @Nullable private InputStream mInputStream;
+    @Nullable private PipedOutputStream mOutputStream;
+    @Nullable private EncryptedFullBackupTask mBackupTask;
+    @Nullable private Future<Void> mBackupTaskFuture;
+    @Nullable private FullBackupCallbacks mFullBackupCallbacks;
+
+    public EncryptedFullBackupDataProcessor(
+            Context context,
+            ExecutorService executorService,
+            CryptoBackupServer cryptoBackupServer,
+            SecureRandom secureRandom,
+            RecoverableKeyStoreSecondaryKey secondaryKey,
+            String packageName) {
+        mContext = checkNotNull(context);
+        mExecutorService = checkNotNull(executorService);
+        mCryptoBackupServer = checkNotNull(cryptoBackupServer);
+        mSecureRandom = checkNotNull(secureRandom);
+        mSecondaryKey = checkNotNull(secondaryKey);
+        mPackageName = checkNotNull(packageName);
+    }
+
+    @Override
+    public boolean initiate(InputStream inputStream) throws IOException {
+        checkState(mBackupTask == null, "initiate() twice");
+
+        this.mInputStream = inputStream;
+        mOutputStream = new PipedOutputStream();
+
+        mBackupTask =
+                EncryptedFullBackupTask.newInstance(
+                        mContext,
+                        mCryptoBackupServer,
+                        mSecureRandom,
+                        mSecondaryKey,
+                        mPackageName,
+                        new PipedInputStream(mOutputStream));
+
+        return true;
+    }
+
+    @Override
+    public void start() {
+        checkState(mBackupTask != null, "start() before initiate()");
+        mBackupTaskFuture = mExecutorService.submit(mBackupTask);
+    }
+
+    @Override
+    public int pushData(int numBytes) {
+        checkState(
+                mBackupTaskFuture != null && mInputStream != null && mOutputStream != null,
+                "pushData() before start()");
+
+        // If the upload has failed then stop without pushing any more bytes.
+        if (mBackupTaskFuture.isDone()) {
+            Optional<Exception> exception = getTaskException();
+            Slog.e(TAG, "Encrypted upload failed", exception.orElse(null));
+            if (exception.isPresent()) {
+                reportNetworkFailureIfNecessary(exception.get());
+
+                if (exception.get().getCause() instanceof SizeQuotaExceededException) {
+                    return BackupTransport.TRANSPORT_QUOTA_EXCEEDED;
+                }
+            }
+
+            return BackupTransport.TRANSPORT_ERROR;
+        }
+
+        try {
+            StreamUtils.copyStream(mInputStream, mOutputStream, numBytes);
+        } catch (IOException e) {
+            Slog.e(TAG, "IOException when processing backup", e);
+            return BackupTransport.TRANSPORT_ERROR;
+        }
+
+        return BackupTransport.TRANSPORT_OK;
+    }
+
+    @Override
+    public void cancel() {
+        checkState(mBackupTaskFuture != null && mBackupTask != null, "cancel() before start()");
+        mBackupTask.cancel();
+        closeStreams();
+    }
+
+    @Override
+    public int finish() {
+        checkState(mBackupTaskFuture != null, "finish() before start()");
+
+        // getTaskException() waits for the task to finish. We must close the streams first, which
+        // causes the task to finish, otherwise it will block forever.
+        closeStreams();
+        Optional<Exception> exception = getTaskException();
+
+        if (exception.isPresent()) {
+            Slog.e(TAG, "Exception during encrypted full backup", exception.get());
+            reportNetworkFailureIfNecessary(exception.get());
+
+            if (exception.get().getCause() instanceof SizeQuotaExceededException) {
+                return BackupTransport.TRANSPORT_QUOTA_EXCEEDED;
+            }
+            return BackupTransport.TRANSPORT_ERROR;
+
+        } else {
+            if (mFullBackupCallbacks != null) {
+                mFullBackupCallbacks.onSuccess();
+            }
+
+            return BackupTransport.TRANSPORT_OK;
+        }
+    }
+
+    private void closeStreams() {
+        StreamUtils.closeQuietly(mInputStream);
+        StreamUtils.closeQuietly(mOutputStream);
+    }
+
+    @Override
+    public void handleCheckSizeRejectionZeroBytes() {
+        cancel();
+    }
+
+    @Override
+    public void handleCheckSizeRejectionQuotaExceeded() {
+        cancel();
+    }
+
+    @Override
+    public void handleSendBytesQuotaExceeded() {
+        cancel();
+    }
+
+    @Override
+    public void attachCallbacks(FullBackupCallbacks fullBackupCallbacks) {
+        this.mFullBackupCallbacks = fullBackupCallbacks;
+    }
+
+    private void reportNetworkFailureIfNecessary(Exception exception) {
+        if (!(exception.getCause() instanceof SizeQuotaExceededException)
+                && mFullBackupCallbacks != null) {
+            mFullBackupCallbacks.onTransferFailed();
+        }
+    }
+
+    private Optional<Exception> getTaskException() {
+        if (mBackupTaskFuture != null) {
+            try {
+                mBackupTaskFuture.get();
+            } catch (InterruptedException | ExecutionException e) {
+                return Optional.of(e);
+            }
+        }
+        return Optional.empty();
+    }
+}
diff --git a/packages/BackupEncryption/src/com/android/server/backup/encryption/tasks/EncryptedKvBackupTask.java b/packages/BackupEncryption/src/com/android/server/backup/encryption/tasks/EncryptedKvBackupTask.java
new file mode 100644
index 0000000..619438c
--- /dev/null
+++ b/packages/BackupEncryption/src/com/android/server/backup/encryption/tasks/EncryptedKvBackupTask.java
@@ -0,0 +1,244 @@
+/*
+ * 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.tasks;
+
+import android.annotation.Nullable;
+import android.app.backup.BackupDataInput;
+import android.content.Context;
+import android.os.ParcelFileDescriptor;
+import android.security.keystore.recovery.InternalRecoveryServiceException;
+import android.security.keystore.recovery.LockScreenRequiredException;
+import android.util.Pair;
+import android.util.Slog;
+
+import com.android.internal.annotations.VisibleForTesting;
+import com.android.server.backup.encryption.CryptoSettings;
+import com.android.server.backup.encryption.chunking.ProtoStore;
+import com.android.server.backup.encryption.client.CryptoBackupServer;
+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 com.android.server.backup.encryption.protos.nano.ChunksMetadataProto;
+import com.android.server.backup.encryption.protos.nano.KeyValueListingProto;
+
+import java.io.IOException;
+import java.lang.reflect.InvocationTargetException;
+import java.security.GeneralSecurityException;
+import java.security.InvalidKeyException;
+import java.security.SecureRandom;
+import java.security.UnrecoverableKeyException;
+import java.util.Optional;
+
+// TODO(b/141975695): Create a base class for EncryptedKvBackupTask and EncryptedFullBackupTask.
+/** Performs encrypted key value backup, handling rotating the tertiary key as necessary. */
+public class EncryptedKvBackupTask {
+    private static final String TAG = "EncryptedKvBackupTask";
+
+    private final TertiaryKeyManager mTertiaryKeyManager;
+    private final RecoverableKeyStoreSecondaryKey mSecondaryKey;
+    private final ProtoStore<KeyValueListingProto.KeyValueListing> mKeyValueListingStore;
+    private final ProtoStore<ChunksMetadataProto.ChunkListing> mChunkListingStore;
+    private final KvBackupEncrypter mKvBackupEncrypter;
+    private final EncryptedBackupTask mEncryptedBackupTask;
+    private final String mPackageName;
+
+    /** Constructs new instances of {@link EncryptedKvBackupTask}. */
+    public static class EncryptedKvBackupTaskFactory {
+        /**
+         * Creates a new instance.
+         *
+         * <p>Either initializes encrypted backup or loads an existing secondary key as necessary.
+         *
+         * @param cryptoSettings to load secondary key state from
+         * @param fileDescriptor to read the backup data from
+         */
+        public EncryptedKvBackupTask newInstance(
+                Context context,
+                SecureRandom secureRandom,
+                CryptoBackupServer cryptoBackupServer,
+                CryptoSettings cryptoSettings,
+                RecoverableKeyStoreSecondaryKeyManager
+                                .RecoverableKeyStoreSecondaryKeyManagerProvider
+                        recoverableSecondaryKeyManagerProvider,
+                ParcelFileDescriptor fileDescriptor,
+                String packageName)
+                throws IOException, UnrecoverableKeyException, LockScreenRequiredException,
+                        InternalRecoveryServiceException, InvalidKeyException {
+            RecoverableKeyStoreSecondaryKey secondaryKey =
+                    new InitializeRecoverableSecondaryKeyTask(
+                                    context,
+                                    cryptoSettings,
+                                    recoverableSecondaryKeyManagerProvider.get(),
+                                    cryptoBackupServer)
+                            .run();
+            KvBackupEncrypter backupEncrypter =
+                    new KvBackupEncrypter(new BackupDataInput(fileDescriptor.getFileDescriptor()));
+            TertiaryKeyManager tertiaryKeyManager =
+                    new TertiaryKeyManager(
+                            context,
+                            secureRandom,
+                            TertiaryKeyRotationScheduler.getInstance(context),
+                            secondaryKey,
+                            packageName);
+
+            return new EncryptedKvBackupTask(
+                    tertiaryKeyManager,
+                    ProtoStore.createKeyValueListingStore(context),
+                    secondaryKey,
+                    ProtoStore.createChunkListingStore(context),
+                    backupEncrypter,
+                    new EncryptedBackupTask(
+                            cryptoBackupServer, secureRandom, packageName, backupEncrypter),
+                    packageName);
+        }
+    }
+
+    @VisibleForTesting
+    EncryptedKvBackupTask(
+            TertiaryKeyManager tertiaryKeyManager,
+            ProtoStore<KeyValueListingProto.KeyValueListing> keyValueListingStore,
+            RecoverableKeyStoreSecondaryKey secondaryKey,
+            ProtoStore<ChunksMetadataProto.ChunkListing> chunkListingStore,
+            KvBackupEncrypter kvBackupEncrypter,
+            EncryptedBackupTask encryptedBackupTask,
+            String packageName) {
+        mTertiaryKeyManager = tertiaryKeyManager;
+        mSecondaryKey = secondaryKey;
+        mKeyValueListingStore = keyValueListingStore;
+        mChunkListingStore = chunkListingStore;
+        mKvBackupEncrypter = kvBackupEncrypter;
+        mEncryptedBackupTask = encryptedBackupTask;
+        mPackageName = packageName;
+    }
+
+    /**
+     * Reads backup data from the file descriptor provided in the construtor, encrypts it and
+     * uploads it to the server.
+     *
+     * <p>The {@code incremental} flag indicates if the backup data provided is incremental or a
+     * complete set. Incremental backup is not possible if no previous crypto state exists, or the
+     * tertiary key must be rotated in the next backup. If the caller requests incremental backup
+     * but it is not possible, then the backup will not start and this method will throw {@link
+     * NonIncrementalBackupRequiredException}.
+     *
+     * <p>TODO(b/70704456): Update return code to indicate that we require non-incremental backup.
+     *
+     * @param incremental {@code true} if the data provided is a diff from the previous backup,
+     *     {@code false} if it is a complete set
+     * @throws NonIncrementalBackupRequiredException if the caller provides an incremental backup but the task
+     *     requires non-incremental backup
+     */
+    public void performBackup(boolean incremental)
+            throws GeneralSecurityException, IOException, NoSuchMethodException,
+            InstantiationException, IllegalAccessException, InvocationTargetException,
+            NonIncrementalBackupRequiredException {
+        if (mTertiaryKeyManager.wasKeyRotated()) {
+            Slog.d(TAG, "Tertiary key is new so clearing package state.");
+            deleteListings(mPackageName);
+        }
+
+        Optional<Pair<KeyValueListingProto.KeyValueListing, ChunksMetadataProto.ChunkListing>>
+                oldListings = getListingsAndEnsureConsistency(mPackageName);
+
+        if (oldListings.isPresent() && !incremental) {
+            Slog.d(
+                    TAG,
+                    "Non-incremental backup requested but incremental state existed, clearing it");
+            deleteListings(mPackageName);
+            oldListings = Optional.empty();
+        }
+
+        if (!oldListings.isPresent() && incremental) {
+            // If we don't have any state then we require a non-incremental backup, but this backup
+            // is incremental.
+            throw new NonIncrementalBackupRequiredException();
+        }
+
+        if (oldListings.isPresent()) {
+            mKvBackupEncrypter.setOldKeyValueListing(oldListings.get().first);
+        }
+
+        ChunksMetadataProto.ChunkListing newChunkListing;
+        if (oldListings.isPresent()) {
+            Slog.v(TAG, "Old listings existed, performing incremental backup");
+            newChunkListing =
+                    mEncryptedBackupTask.performIncrementalBackup(
+                            mTertiaryKeyManager.getKey(),
+                            mTertiaryKeyManager.getWrappedKey(),
+                            oldListings.get().second);
+        } else {
+            Slog.v(TAG, "Old listings did not exist, performing non-incremental backup");
+            // kv backups don't use this salt because they don't involve content-defined chunking.
+            byte[] fingerprintMixerSalt = null;
+            newChunkListing =
+                    mEncryptedBackupTask.performNonIncrementalBackup(
+                            mTertiaryKeyManager.getKey(),
+                            mTertiaryKeyManager.getWrappedKey(),
+                            fingerprintMixerSalt);
+        }
+
+        Slog.v(TAG, "Backup and upload succeeded, saving new listings");
+        saveListings(mPackageName, mKvBackupEncrypter.getNewKeyValueListing(), newChunkListing);
+    }
+
+    private Optional<Pair<KeyValueListingProto.KeyValueListing, ChunksMetadataProto.ChunkListing>>
+            getListingsAndEnsureConsistency(String packageName)
+                    throws IOException, InvocationTargetException, NoSuchMethodException,
+                            InstantiationException, IllegalAccessException {
+        Optional<KeyValueListingProto.KeyValueListing> keyValueListing =
+                mKeyValueListingStore.loadProto(packageName);
+        Optional<ChunksMetadataProto.ChunkListing> chunkListing =
+                mChunkListingStore.loadProto(packageName);
+
+        // Normally either both protos exist or neither exist, but we correct this just in case.
+        boolean bothPresent = keyValueListing.isPresent() && chunkListing.isPresent();
+        if (!bothPresent) {
+            Slog.d(
+                    TAG,
+                    "Both listing were not present, clearing state, key value="
+                            + keyValueListing.isPresent()
+                            + ", chunk="
+                            + chunkListing.isPresent());
+            deleteListings(packageName);
+            return Optional.empty();
+        }
+
+        return Optional.of(Pair.create(keyValueListing.get(), chunkListing.get()));
+    }
+
+    private void saveListings(
+            String packageName,
+            KeyValueListingProto.KeyValueListing keyValueListing,
+            ChunksMetadataProto.ChunkListing chunkListing) {
+        try {
+            mKeyValueListingStore.saveProto(packageName, keyValueListing);
+            mChunkListingStore.saveProto(packageName, chunkListing);
+        } catch (IOException e) {
+            // If a problem occurred while saving either listing then they may be inconsistent, so
+            // delete
+            // both.
+            Slog.w(TAG, "Unable to save listings, deleting both for consistency", e);
+            deleteListings(packageName);
+        }
+    }
+
+    private void deleteListings(String packageName) {
+        mKeyValueListingStore.deleteProto(packageName);
+        mChunkListingStore.deleteProto(packageName);
+    }
+}
diff --git a/packages/BackupEncryption/src/com/android/server/backup/encryption/tasks/EncryptedKvRestoreTask.java b/packages/BackupEncryption/src/com/android/server/backup/encryption/tasks/EncryptedKvRestoreTask.java
new file mode 100644
index 0000000..12b4459
--- /dev/null
+++ b/packages/BackupEncryption/src/com/android/server/backup/encryption/tasks/EncryptedKvRestoreTask.java
@@ -0,0 +1,139 @@
+/*
+ * 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.tasks;
+
+import static com.android.internal.util.Preconditions.checkArgument;
+
+import android.app.backup.BackupDataOutput;
+import android.content.Context;
+import android.os.ParcelFileDescriptor;
+
+import com.android.internal.annotations.VisibleForTesting;
+import com.android.server.backup.encryption.FullRestoreDownloader;
+import com.android.server.backup.encryption.chunking.ChunkHasher;
+import com.android.server.backup.encryption.keys.RecoverableKeyStoreSecondaryKeyManager;
+import com.android.server.backup.encryption.keys.RestoreKeyFetcher;
+import com.android.server.backup.encryption.kv.DecryptedChunkKvOutput;
+import com.android.server.backup.encryption.protos.nano.KeyValuePairProto;
+import com.android.server.backup.encryption.protos.nano.WrappedKeyProto;
+
+import java.io.File;
+import java.io.IOException;
+import java.security.InvalidAlgorithmParameterException;
+import java.security.InvalidKeyException;
+import java.security.KeyException;
+import java.security.NoSuchAlgorithmException;
+
+import javax.crypto.BadPaddingException;
+import javax.crypto.IllegalBlockSizeException;
+import javax.crypto.NoSuchPaddingException;
+import javax.crypto.SecretKey;
+import javax.crypto.ShortBufferException;
+
+/**
+ * Performs a key value restore by downloading the backup set, decrypting it and writing it to the
+ * file provided by backup manager.
+ */
+public class EncryptedKvRestoreTask {
+    private static final String ENCRYPTED_FILE_NAME = "encrypted_kv";
+
+    private final File mTemporaryFolder;
+    private final ChunkHasher mChunkHasher;
+    private final FullRestoreToFileTask mFullRestoreToFileTask;
+    private final BackupFileDecryptorTask mBackupFileDecryptorTask;
+
+    /** Constructs new instances of the task. */
+    public static class EncryptedKvRestoreTaskFactory {
+        /**
+         * Constructs a new instance.
+         *
+         * <p>Fetches the appropriate secondary key and uses this to unwrap the tertiary key. Stores
+         * temporary files in {@link Context#getFilesDir()}.
+         */
+        public EncryptedKvRestoreTask newInstance(
+                Context context,
+                RecoverableKeyStoreSecondaryKeyManager
+                                .RecoverableKeyStoreSecondaryKeyManagerProvider
+                        recoverableSecondaryKeyManagerProvider,
+                FullRestoreDownloader fullRestoreDownloader,
+                String secondaryKeyAlias,
+                WrappedKeyProto.WrappedKey wrappedTertiaryKey)
+                throws EncryptedRestoreException, NoSuchAlgorithmException, NoSuchPaddingException,
+                        KeyException, InvalidAlgorithmParameterException {
+            SecretKey tertiaryKey =
+                    RestoreKeyFetcher.unwrapTertiaryKey(
+                            recoverableSecondaryKeyManagerProvider,
+                            secondaryKeyAlias,
+                            wrappedTertiaryKey);
+
+            return new EncryptedKvRestoreTask(
+                    context.getFilesDir(),
+                    new ChunkHasher(tertiaryKey),
+                    new FullRestoreToFileTask(fullRestoreDownloader),
+                    new BackupFileDecryptorTask(tertiaryKey));
+        }
+    }
+
+    @VisibleForTesting
+    EncryptedKvRestoreTask(
+            File temporaryFolder,
+            ChunkHasher chunkHasher,
+            FullRestoreToFileTask fullRestoreToFileTask,
+            BackupFileDecryptorTask backupFileDecryptorTask) {
+        checkArgument(
+                temporaryFolder.isDirectory(), "Temporary folder must be an existing directory");
+
+        mTemporaryFolder = temporaryFolder;
+        mChunkHasher = chunkHasher;
+        mFullRestoreToFileTask = fullRestoreToFileTask;
+        mBackupFileDecryptorTask = backupFileDecryptorTask;
+    }
+
+    /**
+     * Runs the restore, writing the pairs in lexicographical order to the given file descriptor.
+     *
+     * <p>This will block for the duration of the restore.
+     *
+     * @throws EncryptedRestoreException if there is a problem decrypting or verifying the backup
+     */
+    public void getRestoreData(ParcelFileDescriptor output)
+            throws IOException, EncryptedRestoreException, BadPaddingException,
+                    InvalidAlgorithmParameterException, NoSuchAlgorithmException,
+                    IllegalBlockSizeException, ShortBufferException, InvalidKeyException {
+        File encryptedFile = new File(mTemporaryFolder, ENCRYPTED_FILE_NAME);
+        try {
+            downloadDecryptAndWriteBackup(encryptedFile, output);
+        } finally {
+            encryptedFile.delete();
+        }
+    }
+
+    private void downloadDecryptAndWriteBackup(File encryptedFile, ParcelFileDescriptor output)
+            throws EncryptedRestoreException, IOException, BadPaddingException, InvalidKeyException,
+                    NoSuchAlgorithmException, IllegalBlockSizeException, ShortBufferException,
+                    InvalidAlgorithmParameterException {
+        mFullRestoreToFileTask.restoreToFile(encryptedFile);
+        DecryptedChunkKvOutput decryptedChunkKvOutput = new DecryptedChunkKvOutput(mChunkHasher);
+        mBackupFileDecryptorTask.decryptFile(encryptedFile, decryptedChunkKvOutput);
+
+        BackupDataOutput backupDataOutput = new BackupDataOutput(output.getFileDescriptor());
+        for (KeyValuePairProto.KeyValuePair pair : decryptedChunkKvOutput.getPairs()) {
+            backupDataOutput.writeEntityHeader(pair.key, pair.value.length);
+            backupDataOutput.writeEntityData(pair.value, pair.value.length);
+        }
+    }
+}
diff --git a/core/java/android/hardware/biometrics/IBiometricConfirmDeviceCredentialCallback.aidl b/packages/BackupEncryption/src/com/android/server/backup/encryption/tasks/NonIncrementalBackupRequiredException.java
similarity index 67%
copy from core/java/android/hardware/biometrics/IBiometricConfirmDeviceCredentialCallback.aidl
copy to packages/BackupEncryption/src/com/android/server/backup/encryption/tasks/NonIncrementalBackupRequiredException.java
index 8b35852..a3eda7d 100644
--- a/core/java/android/hardware/biometrics/IBiometricConfirmDeviceCredentialCallback.aidl
+++ b/packages/BackupEncryption/src/com/android/server/backup/encryption/tasks/NonIncrementalBackupRequiredException.java
@@ -14,13 +14,12 @@
  * limitations under the License.
  */
 
-package android.hardware.biometrics;
 
+package com.android.server.backup.encryption.tasks;
+
+// TODO(141840878): Update documentation.
 /**
- * Communication channel between ConfirmDeviceCredential / ConfirmLock* and BiometricService.
- * @hide
+ * Exception thrown when the framework provides an incremental backup but the transport requires a
+ * non-incremental backup.
  */
-interface IBiometricConfirmDeviceCredentialCallback {
-    // Invoked when authentication should be canceled.
-    oneway void cancel();
-}
\ No newline at end of file
+public class NonIncrementalBackupRequiredException extends Exception {}
diff --git a/packages/BackupEncryption/test/robolectric-integration/Android.bp b/packages/BackupEncryption/test/robolectric-integration/Android.bp
index f696278..67365df 100644
--- a/packages/BackupEncryption/test/robolectric-integration/Android.bp
+++ b/packages/BackupEncryption/test/robolectric-integration/Android.bp
@@ -23,6 +23,7 @@
         "platform-test-annotations",
         "testng",
         "truth-prebuilt",
+        "BackupEncryptionRoboTests",
     ],
     static_libs: [
         "androidx.test.core",
diff --git a/packages/BackupEncryption/test/robolectric-integration/src/com/android/server/backup/encryption/RoundTripTest.java b/packages/BackupEncryption/test/robolectric-integration/src/com/android/server/backup/encryption/RoundTripTest.java
index 8ec68fd..a432d91 100644
--- a/packages/BackupEncryption/test/robolectric-integration/src/com/android/server/backup/encryption/RoundTripTest.java
+++ b/packages/BackupEncryption/test/robolectric-integration/src/com/android/server/backup/encryption/RoundTripTest.java
@@ -19,21 +19,35 @@
 import static com.google.common.truth.Truth.assertThat;
 
 import android.content.Context;
+import android.os.ParcelFileDescriptor;
+import android.security.keystore.recovery.InternalRecoveryServiceException;
+import android.security.keystore.recovery.RecoveryController;
 
 import androidx.test.core.app.ApplicationProvider;
 
 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.keys.RecoverableKeyStoreSecondaryKeyManager;
 import com.android.server.backup.encryption.keys.TertiaryKeyManager;
 import com.android.server.backup.encryption.keys.TertiaryKeyRotationScheduler;
 import com.android.server.backup.encryption.protos.nano.WrappedKeyProto;
 import com.android.server.backup.encryption.tasks.EncryptedFullBackupTask;
 import com.android.server.backup.encryption.tasks.EncryptedFullRestoreTask;
+import com.android.server.backup.encryption.tasks.EncryptedKvBackupTask;
+import com.android.server.backup.encryption.tasks.EncryptedKvRestoreTask;
+import com.android.server.testing.shadows.DataEntity;
+import com.android.server.testing.shadows.ShadowBackupDataInput;
+import com.android.server.testing.shadows.ShadowBackupDataOutput;
+import com.android.server.testing.shadows.ShadowRecoveryController;
 
 import org.junit.Before;
 import org.junit.Test;
 import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
 import org.robolectric.RobolectricTestRunner;
+import org.robolectric.annotation.Config;
 
 import java.io.ByteArrayInputStream;
 import java.io.ByteArrayOutputStream;
@@ -42,15 +56,29 @@
 import java.security.InvalidKeyException;
 import java.security.NoSuchAlgorithmException;
 import java.security.SecureRandom;
+import java.util.Optional;
 import java.util.Map;
+import java.util.Set;
 
 import javax.crypto.IllegalBlockSizeException;
 import javax.crypto.KeyGenerator;
 import javax.crypto.NoSuchPaddingException;
 import javax.crypto.SecretKey;
 
+@Config(
+        shadows = {
+            ShadowBackupDataInput.class,
+            ShadowBackupDataOutput.class,
+            ShadowRecoveryController.class
+        })
 @RunWith(RobolectricTestRunner.class)
 public class RoundTripTest {
+    private static final DataEntity[] KEY_VALUE_DATA = {
+        new DataEntity("test_key_1", "test_value_1"),
+        new DataEntity("test_key_2", "test_value_2"),
+        new DataEntity("test_key_3", "test_value_3")
+    };
+
     /** Amount of data we want to round trip in this test */
     private static final int TEST_DATA_SIZE = 1024 * 1024; // 1MB
 
@@ -59,6 +87,7 @@
 
     /** Key parameters used for the secondary encryption key */
     private static final String KEY_ALGORITHM = "AES";
+
     private static final int KEY_SIZE_BITS = 256;
 
     /** Package name for our test package */
@@ -77,25 +106,82 @@
     private RecoverableKeyStoreSecondaryKey mSecondaryKey;
 
     /** Source of random material which is considered non-predictable in its' generation */
-    private SecureRandom mSecureRandom = new SecureRandom();
+    private final SecureRandom mSecureRandom = new SecureRandom();
+
+    private RecoverableKeyStoreSecondaryKeyManager.RecoverableKeyStoreSecondaryKeyManagerProvider
+            mSecondaryKeyManagerProvider;
+    private DummyServer mDummyServer;
+    private RecoveryController mRecoveryController;
+
+    @Mock private ParcelFileDescriptor mParcelFileDescriptor;
 
     @Before
-    public void setUp() throws NoSuchAlgorithmException {
+    public void setUp() throws NoSuchAlgorithmException, InternalRecoveryServiceException {
+        MockitoAnnotations.initMocks(this);
+
+        ShadowBackupDataInput.reset();
+        ShadowBackupDataOutput.reset();
+
         mContext = ApplicationProvider.getApplicationContext();
         mSecondaryKey = new RecoverableKeyStoreSecondaryKey(TEST_KEY_ALIAS, generateAesKey());
+        mDummyServer = new DummyServer();
+        mSecondaryKeyManagerProvider =
+                () ->
+                        new RecoverableKeyStoreSecondaryKeyManager(
+                                RecoveryController.getInstance(mContext), mSecureRandom);
+
         fillBuffer(mOriginalData);
     }
 
     @Test
-    public void testRoundTrip() throws Exception {
-        byte[] backupData = performBackup(mOriginalData);
+    public void testFull_nonIncrementalBackupAndRestoreAreSuccessful() throws Exception {
+        byte[] backupData = performFullBackup(mOriginalData);
         assertThat(backupData).isNotEqualTo(mOriginalData);
-        byte[] restoredData = performRestore(backupData);
+        byte[] restoredData = performFullRestore(backupData);
         assertThat(restoredData).isEqualTo(mOriginalData);
     }
 
-    /** Perform a backup and return the backed-up representation of the data */
-    private byte[] performBackup(byte[] backupData) throws Exception {
+    @Test
+    public void testKeyValue_nonIncrementalBackupAndRestoreAreSuccessful() throws Exception {
+        byte[] backupData = performNonIncrementalKeyValueBackup(KEY_VALUE_DATA);
+
+        // Get the secondary key used to do backup.
+        Optional<RecoverableKeyStoreSecondaryKey> secondaryKey =
+                mSecondaryKeyManagerProvider.get().get(mDummyServer.mSecondaryKeyAlias);
+        assertThat(secondaryKey.isPresent()).isTrue();
+
+        Set<DataEntity> restoredData = performKeyValueRestore(backupData, secondaryKey.get());
+
+        assertThat(restoredData).containsExactly(KEY_VALUE_DATA).inOrder();
+    }
+
+    /** Perform a key/value backup and return the backed-up representation of the data */
+    private byte[] performNonIncrementalKeyValueBackup(DataEntity[] backupData)
+            throws Exception {
+        // Populate test key/value data.
+        for (DataEntity entity : backupData) {
+            ShadowBackupDataInput.addEntity(entity);
+        }
+
+        EncryptedKvBackupTask.EncryptedKvBackupTaskFactory backupTaskFactory =
+                new EncryptedKvBackupTask.EncryptedKvBackupTaskFactory();
+        EncryptedKvBackupTask backupTask =
+                backupTaskFactory.newInstance(
+                        mContext,
+                        mSecureRandom,
+                        mDummyServer,
+                        CryptoSettings.getInstance(mContext),
+                        mSecondaryKeyManagerProvider,
+                        mParcelFileDescriptor,
+                        TEST_PACKAGE_NAME);
+
+        backupTask.performBackup(/* incremental */ false);
+
+        return mDummyServer.mStoredData;
+    }
+
+    /** Perform a full backup and return the backed-up representation of the data */
+    private byte[] performFullBackup(byte[] backupData) throws Exception {
         DummyServer dummyServer = new DummyServer();
         EncryptedFullBackupTask backupTask =
                 EncryptedFullBackupTask.newInstance(
@@ -109,8 +195,24 @@
         return dummyServer.mStoredData;
     }
 
-    /** Perform a restore and resturn the bytes obtained from the restore process */
-    private byte[] performRestore(byte[] backupData)
+    private Set<DataEntity> performKeyValueRestore(
+            byte[] backupData, RecoverableKeyStoreSecondaryKey secondaryKey) throws Exception {
+        EncryptedKvRestoreTask.EncryptedKvRestoreTaskFactory restoreTaskFactory =
+                new EncryptedKvRestoreTask.EncryptedKvRestoreTaskFactory();
+        EncryptedKvRestoreTask restoreTask =
+                restoreTaskFactory.newInstance(
+                        mContext,
+                        mSecondaryKeyManagerProvider,
+                        new FakeFullRestoreDownloader(backupData),
+                        secondaryKey.getAlias(),
+                        KeyWrapUtils.wrap(
+                                secondaryKey.getSecretKey(), getTertiaryKey(secondaryKey)));
+        restoreTask.getRestoreData(mParcelFileDescriptor);
+        return ShadowBackupDataOutput.getEntities();
+    }
+
+    /** Perform a full restore and return the bytes obtained from the restore process */
+    private byte[] performFullRestore(byte[] backupData)
             throws IOException, NoSuchAlgorithmException, NoSuchPaddingException,
                     InvalidAlgorithmParameterException, InvalidKeyException,
                     IllegalBlockSizeException {
@@ -118,7 +220,9 @@
 
         EncryptedFullRestoreTask restoreTask =
                 EncryptedFullRestoreTask.newInstance(
-                        mContext, new FakeFullRestoreDownloader(backupData), getTertiaryKey());
+                        mContext,
+                        new FakeFullRestoreDownloader(backupData),
+                        getTertiaryKey(mSecondaryKey));
 
         byte[] buffer = new byte[READ_BUFFER_SIZE];
         int bytesRead = restoreTask.readNextChunk(buffer);
@@ -131,7 +235,7 @@
     }
 
     /** Get the tertiary key for our test package from the key manager */
-    private SecretKey getTertiaryKey()
+    private SecretKey getTertiaryKey(RecoverableKeyStoreSecondaryKey secondaryKey)
             throws IllegalBlockSizeException, InvalidAlgorithmParameterException,
                     NoSuchAlgorithmException, IOException, NoSuchPaddingException,
                     InvalidKeyException {
@@ -140,7 +244,7 @@
                         mContext,
                         mSecureRandom,
                         TertiaryKeyRotationScheduler.getInstance(mContext),
-                        mSecondaryKey,
+                        secondaryKey,
                         TEST_PACKAGE_NAME);
         return tertiaryKeyManager.getKey();
     }
@@ -162,13 +266,13 @@
     }
 
     /**
-     * Dummy backup data endpoint. This stores the data so we can use it
-     * in subsequent test steps.
+     * Dummy backup data endpoint. This stores the data so we can use it in subsequent test steps.
      */
     private static class DummyServer implements CryptoBackupServer {
         private static final String DUMMY_DOC_ID = "DummyDoc";
 
         byte[] mStoredData = null;
+        String mSecondaryKeyAlias;
 
         @Override
         public String uploadIncrementalBackup(
@@ -190,7 +294,7 @@
         @Override
         public void setActiveSecondaryKeyAlias(
                 String keyAlias, Map<String, WrappedKeyProto.WrappedKey> tertiaryKeys) {
-            throw new RuntimeException("Not Implemented");
+            mSecondaryKeyAlias = keyAlias;
         }
     }
 
diff --git a/packages/BackupEncryption/test/robolectric/src/com/android/server/backup/encryption/StreamUtilsTest.java b/packages/BackupEncryption/test/robolectric/src/com/android/server/backup/encryption/StreamUtilsTest.java
new file mode 100644
index 0000000..a95e87e
--- /dev/null
+++ b/packages/BackupEncryption/test/robolectric/src/com/android/server/backup/encryption/StreamUtilsTest.java
@@ -0,0 +1,75 @@
+/*
+ * 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.google.common.truth.Truth.assertThat;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.robolectric.RobolectricTestRunner;
+
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+
+@RunWith(RobolectricTestRunner.class)
+public class StreamUtilsTest {
+    private static final int SOURCE_DATA_SIZE = 64;
+
+    private byte[] mSourceData;
+
+    private InputStream mSource;
+    private ByteArrayOutputStream mDestination;
+
+    @Before
+    public void setUp() {
+        mSourceData = new byte[SOURCE_DATA_SIZE];
+        for (byte i = 0; i < SOURCE_DATA_SIZE; i++) {
+            mSourceData[i] = i;
+        }
+        mSource = new ByteArrayInputStream(mSourceData);
+        mDestination = new ByteArrayOutputStream();
+    }
+
+    @Test
+    public void copyStream_copiesAllBytesIfAsked() throws IOException {
+        StreamUtils.copyStream(mSource, mDestination, mSourceData.length);
+        assertOutputHasBytes(mSourceData.length);
+    }
+
+    @Test
+    public void copyStream_stopsShortIfAsked() throws IOException {
+        StreamUtils.copyStream(mSource, mDestination, mSourceData.length - 10);
+        assertOutputHasBytes(mSourceData.length - 10);
+    }
+
+    @Test
+    public void copyStream_stopsShortIfAskedToCopyMoreThanAvailable() throws IOException {
+        StreamUtils.copyStream(mSource, mDestination, mSourceData.length + 10);
+        assertOutputHasBytes(mSourceData.length);
+    }
+
+    private void assertOutputHasBytes(int count) {
+        byte[] output = mDestination.toByteArray();
+        assertThat(output.length).isEqualTo(count);
+        for (int i = 0; i < count; i++) {
+            assertThat(output[i]).isEqualTo(mSourceData[i]);
+        }
+    }
+}
diff --git a/packages/BackupEncryption/test/robolectric/src/com/android/server/backup/encryption/tasks/ClearCryptoStateTaskTest.java b/packages/BackupEncryption/test/robolectric/src/com/android/server/backup/encryption/tasks/ClearCryptoStateTaskTest.java
new file mode 100644
index 0000000..81bfce1
--- /dev/null
+++ b/packages/BackupEncryption/test/robolectric/src/com/android/server/backup/encryption/tasks/ClearCryptoStateTaskTest.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.server.backup.encryption.tasks;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import static org.mockito.Mockito.spy;
+
+import android.content.Context;
+import android.platform.test.annotations.Presubmit;
+
+import androidx.test.core.app.ApplicationProvider;
+
+import com.android.server.backup.encryption.CryptoSettings;
+import com.android.server.backup.encryption.chunking.ProtoStore;
+import com.android.server.backup.encryption.protos.nano.ChunksMetadataProto.ChunkListing;
+import com.android.server.backup.encryption.protos.nano.KeyValueListingProto.KeyValueListing;
+import com.android.server.backup.encryption.storage.BackupEncryptionDb;
+import com.android.server.backup.encryption.storage.TertiaryKey;
+import com.android.server.backup.encryption.storage.TertiaryKeysTable;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.robolectric.RobolectricTestRunner;
+
+@RunWith(RobolectricTestRunner.class)
+@Presubmit
+public class ClearCryptoStateTaskTest {
+    private static final String TEST_PACKAGE_NAME = "com.android.example";
+
+    private ClearCryptoStateTask mClearCryptoStateTask;
+    private CryptoSettings mCryptoSettings;
+    private Context mApplication;
+
+    @Before
+    public void setUp() {
+        mApplication = ApplicationProvider.getApplicationContext();
+        mCryptoSettings = spy(CryptoSettings.getInstanceForTesting(mApplication));
+        mClearCryptoStateTask = new ClearCryptoStateTask(mApplication, mCryptoSettings);
+    }
+
+    @Test
+    public void run_clearsChunkListingProtoState() throws Exception {
+        String packageName = TEST_PACKAGE_NAME;
+        ChunkListing chunkListing = new ChunkListing();
+        ProtoStore.createChunkListingStore(mApplication).saveProto(packageName, chunkListing);
+
+        mClearCryptoStateTask.run();
+
+        assertThat(
+                        ProtoStore.createChunkListingStore(mApplication)
+                                .loadProto(packageName)
+                                .isPresent())
+                .isFalse();
+    }
+
+    @Test
+    public void run_clearsKeyValueProtoState() throws Exception {
+        String packageName = TEST_PACKAGE_NAME;
+        KeyValueListing keyValueListing = new KeyValueListing();
+        ProtoStore.createKeyValueListingStore(mApplication).saveProto(packageName, keyValueListing);
+
+        mClearCryptoStateTask.run();
+
+        assertThat(
+                        ProtoStore.createKeyValueListingStore(mApplication)
+                                .loadProto(packageName)
+                                .isPresent())
+                .isFalse();
+    }
+
+    @Test
+    public void run_clearsTertiaryKeysTable() throws Exception {
+        String secondaryKeyAlias = "bob";
+        TertiaryKeysTable tertiaryKeysTable =
+                BackupEncryptionDb.newInstance(mApplication).getTertiaryKeysTable();
+        tertiaryKeysTable.addKey(
+                new TertiaryKey(
+                        secondaryKeyAlias, "packageName", /*wrappedKeyBytes=*/ new byte[0]));
+
+        mClearCryptoStateTask.run();
+
+        assertThat(tertiaryKeysTable.getAllKeys(secondaryKeyAlias)).isEmpty();
+    }
+
+    @Test
+    public void run_clearsSettings() {
+        mCryptoSettings.setSecondaryLastRotated(100001);
+
+        mClearCryptoStateTask.run();
+
+        assertThat(mCryptoSettings.getSecondaryLastRotated().isPresent()).isFalse();
+    }
+}
diff --git a/packages/BackupEncryption/test/robolectric/src/com/android/server/backup/encryption/tasks/EncryptedFullBackupDataProcessorTest.java b/packages/BackupEncryption/test/robolectric/src/com/android/server/backup/encryption/tasks/EncryptedFullBackupDataProcessorTest.java
new file mode 100644
index 0000000..675d03f
--- /dev/null
+++ b/packages/BackupEncryption/test/robolectric/src/com/android/server/backup/encryption/tasks/EncryptedFullBackupDataProcessorTest.java
@@ -0,0 +1,387 @@
+/*
+ * 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.tasks;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.never;
+import static org.mockito.Mockito.verify;
+import static org.testng.Assert.assertThrows;
+
+import android.annotation.Nullable;
+import android.app.backup.BackupTransport;
+import android.platform.test.annotations.Presubmit;
+
+import androidx.test.core.app.ApplicationProvider;
+
+import com.android.server.backup.encryption.FullBackupDataProcessor;
+import com.android.server.backup.encryption.chunking.ProtoStore;
+import com.android.server.backup.encryption.client.CryptoBackupServer;
+import com.android.server.backup.encryption.keys.RecoverableKeyStoreSecondaryKey;
+import com.android.server.backup.encryption.keys.TertiaryKeyManager;
+import com.android.server.backup.encryption.protos.nano.ChunksMetadataProto;
+import com.android.server.backup.encryption.testing.QueuingNonAutomaticExecutorService;
+
+import com.google.common.io.ByteStreams;
+import com.google.common.primitives.Bytes;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+import org.robolectric.RobolectricTestRunner;
+import org.robolectric.annotation.Config;
+import org.robolectric.annotation.Implementation;
+import org.robolectric.annotation.Implements;
+
+import java.io.ByteArrayInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.security.GeneralSecurityException;
+import java.security.SecureRandom;
+
+import javax.crypto.spec.SecretKeySpec;
+
+@RunWith(RobolectricTestRunner.class)
+@Presubmit
+@Config(
+        shadows = {
+            EncryptedFullBackupDataProcessorTest.ShadowEncryptedFullBackupTask.class,
+        })
+public class EncryptedFullBackupDataProcessorTest {
+
+    private static final String KEY_GENERATOR_ALGORITHM = "AES";
+
+    private static final String TEST_PACKAGE = "com.example.app1";
+    private static final byte[] TEST_DATA_1 = {1, 2, 3, 4};
+    private static final byte[] TEST_DATA_2 = {5, 6, 7, 8};
+
+    private final RecoverableKeyStoreSecondaryKey mTestSecondaryKey =
+            new RecoverableKeyStoreSecondaryKey(
+                    /*alias=*/ "test_key",
+                    new SecretKeySpec(
+                            new byte[] {
+                                1, 2, 3,
+                            },
+                            KEY_GENERATOR_ALGORITHM));
+
+    private QueuingNonAutomaticExecutorService mExecutorService;
+    private FullBackupDataProcessor mFullBackupDataProcessor;
+    @Mock private FullBackupDataProcessor.FullBackupCallbacks mFullBackupCallbacks;
+
+    @Before
+    public void setUp() {
+        MockitoAnnotations.initMocks(this);
+
+        mExecutorService = new QueuingNonAutomaticExecutorService();
+        mFullBackupDataProcessor =
+                new EncryptedFullBackupDataProcessor(
+                        ApplicationProvider.getApplicationContext(),
+                        mExecutorService,
+                        mock(CryptoBackupServer.class),
+                        new SecureRandom(),
+                        mTestSecondaryKey,
+                        TEST_PACKAGE);
+    }
+
+    @After
+    public void tearDown() {
+        ShadowEncryptedFullBackupTask.reset();
+    }
+
+    @Test
+    public void initiate_callTwice_throws() throws Exception {
+        mFullBackupDataProcessor.initiate(new ByteArrayInputStream(new byte[10]));
+
+        assertThrows(
+                IllegalStateException.class,
+                () -> mFullBackupDataProcessor.initiate(new ByteArrayInputStream(new byte[10])));
+    }
+
+    @Test
+    public void pushData_writesDataToTask() throws Exception {
+        byte[] inputData = Bytes.concat(TEST_DATA_1, TEST_DATA_2);
+
+        mFullBackupDataProcessor.initiate(new ByteArrayInputStream(inputData));
+        mFullBackupDataProcessor.start();
+        mFullBackupDataProcessor.pushData(TEST_DATA_1.length);
+        mFullBackupDataProcessor.pushData(TEST_DATA_2.length);
+        finishBackupTask();
+        mFullBackupDataProcessor.finish();
+
+        byte[] result = ByteStreams.toByteArray(ShadowEncryptedFullBackupTask.sInputStream);
+        assertThat(result).isEqualTo(Bytes.concat(TEST_DATA_1, TEST_DATA_2));
+    }
+
+    @Test
+    public void pushData_noError_returnsOk() throws Exception {
+        mFullBackupDataProcessor.initiate(new ByteArrayInputStream(TEST_DATA_1));
+        mFullBackupDataProcessor.start();
+        int result = mFullBackupDataProcessor.pushData(TEST_DATA_1.length);
+        finishBackupTask();
+        mFullBackupDataProcessor.finish();
+
+        assertThat(result).isEqualTo(BackupTransport.TRANSPORT_OK);
+    }
+
+    @Test
+    public void pushData_ioExceptionOnCopy_returnsError() throws Exception {
+        mFullBackupDataProcessor.initiate(new ByteArrayInputStream(TEST_DATA_1));
+        mFullBackupDataProcessor.start();
+
+        // Close the stream so there's an IO error when the processor tries to write to it.
+        ShadowEncryptedFullBackupTask.sInputStream.close();
+        int result = mFullBackupDataProcessor.pushData(TEST_DATA_1.length);
+
+        finishBackupTask();
+        mFullBackupDataProcessor.finish();
+
+        assertThat(result).isEqualTo(BackupTransport.TRANSPORT_ERROR);
+    }
+
+    @Test
+    public void pushData_exceptionDuringUpload_returnsError() throws Exception {
+        byte[] inputData = Bytes.concat(TEST_DATA_1, TEST_DATA_2);
+
+        mFullBackupDataProcessor.initiate(new ByteArrayInputStream(inputData));
+        mFullBackupDataProcessor.start();
+        mFullBackupDataProcessor.pushData(TEST_DATA_1.length);
+        finishBackupTaskWithException(new IOException("Test exception"));
+        int result = mFullBackupDataProcessor.pushData(TEST_DATA_2.length);
+
+        assertThat(result).isEqualTo(BackupTransport.TRANSPORT_ERROR);
+    }
+
+    @Test
+    public void pushData_quotaExceptionDuringUpload_doesNotLogAndReturnsQuotaExceeded()
+            throws Exception {
+        mFullBackupDataProcessor.attachCallbacks(mFullBackupCallbacks);
+        byte[] inputData = Bytes.concat(TEST_DATA_1, TEST_DATA_2);
+
+        mFullBackupDataProcessor.initiate(new ByteArrayInputStream(inputData));
+        mFullBackupDataProcessor.start();
+        mFullBackupDataProcessor.pushData(TEST_DATA_1.length);
+        finishBackupTaskWithException(new SizeQuotaExceededException());
+        int result = mFullBackupDataProcessor.pushData(TEST_DATA_2.length);
+
+        assertThat(result).isEqualTo(BackupTransport.TRANSPORT_QUOTA_EXCEEDED);
+
+        verify(mFullBackupCallbacks, never()).onSuccess();
+        verify(mFullBackupCallbacks, never())
+                .onTransferFailed(); // FullBackupSession will handle this.
+    }
+
+    @Test
+    public void pushData_unexpectedEncryptedBackup_logs() throws Exception {
+        byte[] inputData = Bytes.concat(TEST_DATA_1, TEST_DATA_2);
+
+        mFullBackupDataProcessor.initiate(new ByteArrayInputStream(inputData));
+        mFullBackupDataProcessor.start();
+        mFullBackupDataProcessor.pushData(TEST_DATA_1.length);
+        finishBackupTaskWithException(new GeneralSecurityException());
+        int result = mFullBackupDataProcessor.pushData(TEST_DATA_2.length);
+
+        assertThat(result).isEqualTo(BackupTransport.TRANSPORT_ERROR);
+    }
+
+    @Test
+    public void pushData_permanentExceptionDuringUpload_callsErrorCallback() throws Exception {
+        mFullBackupDataProcessor.attachCallbacks(mFullBackupCallbacks);
+        byte[] inputData = Bytes.concat(TEST_DATA_1, TEST_DATA_2);
+
+        mFullBackupDataProcessor.initiate(new ByteArrayInputStream(inputData));
+        mFullBackupDataProcessor.start();
+        mFullBackupDataProcessor.pushData(TEST_DATA_1.length);
+        finishBackupTaskWithException(new IOException());
+        mFullBackupDataProcessor.pushData(TEST_DATA_2.length);
+
+        verify(mFullBackupCallbacks, never()).onSuccess();
+        verify(mFullBackupCallbacks).onTransferFailed();
+    }
+
+    @Test
+    public void pushData_beforeInitiate_throws() {
+        assertThrows(
+                IllegalStateException.class,
+                () -> mFullBackupDataProcessor.pushData(/*numBytes=*/ 10));
+    }
+
+    @Test
+    public void cancel_cancelsTask() throws Exception {
+        mFullBackupDataProcessor.initiate(new ByteArrayInputStream(TEST_DATA_1));
+        mFullBackupDataProcessor.start();
+        mFullBackupDataProcessor.pushData(TEST_DATA_1.length);
+        mFullBackupDataProcessor.cancel();
+
+        assertThat(ShadowEncryptedFullBackupTask.sCancelled).isTrue();
+    }
+
+    @Test
+    public void cancel_beforeInitiate_throws() {
+        assertThrows(IllegalStateException.class, () -> mFullBackupDataProcessor.cancel());
+    }
+
+    @Test
+    public void finish_noException_returnsTransportOk() throws Exception {
+        mFullBackupDataProcessor.initiate(new ByteArrayInputStream(TEST_DATA_1));
+        mFullBackupDataProcessor.start();
+        mFullBackupDataProcessor.pushData(TEST_DATA_1.length);
+        finishBackupTask();
+        int result = mFullBackupDataProcessor.finish();
+
+        assertThat(result).isEqualTo(BackupTransport.TRANSPORT_OK);
+    }
+
+    @Test
+    public void finish_exceptionDuringUpload_returnsTransportError() throws Exception {
+        mFullBackupDataProcessor.initiate(new ByteArrayInputStream(TEST_DATA_1));
+        mFullBackupDataProcessor.start();
+        mFullBackupDataProcessor.pushData(TEST_DATA_1.length);
+        finishBackupTaskWithException(new IOException("Test exception"));
+        int result = mFullBackupDataProcessor.finish();
+
+        assertThat(result).isEqualTo(BackupTransport.TRANSPORT_ERROR);
+    }
+
+    @Test
+    public void finish_successfulBackup_callsSuccessCallback() throws Exception {
+        mFullBackupDataProcessor.attachCallbacks(mFullBackupCallbacks);
+
+        mFullBackupDataProcessor.initiate(new ByteArrayInputStream(TEST_DATA_1));
+        mFullBackupDataProcessor.start();
+        mFullBackupDataProcessor.pushData(TEST_DATA_1.length);
+        finishBackupTask();
+        mFullBackupDataProcessor.finish();
+
+        verify(mFullBackupCallbacks).onSuccess();
+        verify(mFullBackupCallbacks, never()).onTransferFailed();
+    }
+
+    @Test
+    public void finish_backupFailedWithPermanentError_callsErrorCallback() throws Exception {
+        mFullBackupDataProcessor.attachCallbacks(mFullBackupCallbacks);
+
+        mFullBackupDataProcessor.initiate(new ByteArrayInputStream(TEST_DATA_1));
+        mFullBackupDataProcessor.start();
+        mFullBackupDataProcessor.pushData(TEST_DATA_1.length);
+        finishBackupTaskWithException(new IOException());
+        mFullBackupDataProcessor.finish();
+
+        verify(mFullBackupCallbacks, never()).onSuccess();
+        verify(mFullBackupCallbacks).onTransferFailed();
+    }
+
+    @Test
+    public void finish_backupFailedWithQuotaException_doesNotCallbackAndReturnsQuotaExceeded()
+            throws Exception {
+        mFullBackupDataProcessor.attachCallbacks(mFullBackupCallbacks);
+
+        mFullBackupDataProcessor.initiate(new ByteArrayInputStream(TEST_DATA_1));
+        mFullBackupDataProcessor.start();
+        mFullBackupDataProcessor.pushData(TEST_DATA_1.length);
+        finishBackupTaskWithException(new SizeQuotaExceededException());
+        int result = mFullBackupDataProcessor.finish();
+
+        assertThat(result).isEqualTo(BackupTransport.TRANSPORT_QUOTA_EXCEEDED);
+        verify(mFullBackupCallbacks, never()).onSuccess();
+        verify(mFullBackupCallbacks, never())
+                .onTransferFailed(); // FullBackupSession will handle this.
+    }
+
+    @Test
+    public void finish_beforeInitiate_throws() {
+        assertThrows(IllegalStateException.class, () -> mFullBackupDataProcessor.finish());
+    }
+
+    @Test
+    public void handleCheckSizeRejectionZeroBytes_cancelsTask() throws Exception {
+        mFullBackupDataProcessor.initiate(new ByteArrayInputStream(new byte[10]));
+        mFullBackupDataProcessor.start();
+        mFullBackupDataProcessor.handleCheckSizeRejectionZeroBytes();
+
+        assertThat(ShadowEncryptedFullBackupTask.sCancelled).isTrue();
+    }
+
+    @Test
+    public void handleCheckSizeRejectionQuotaExceeded_cancelsTask() throws Exception {
+        mFullBackupDataProcessor.initiate(new ByteArrayInputStream(TEST_DATA_1));
+        mFullBackupDataProcessor.start();
+        mFullBackupDataProcessor.pushData(TEST_DATA_1.length);
+        mFullBackupDataProcessor.handleCheckSizeRejectionQuotaExceeded();
+
+        assertThat(ShadowEncryptedFullBackupTask.sCancelled).isTrue();
+    }
+
+    @Test
+    public void handleSendBytesQuotaExceeded_cancelsTask() throws Exception {
+        mFullBackupDataProcessor.initiate(new ByteArrayInputStream(TEST_DATA_1));
+        mFullBackupDataProcessor.start();
+        mFullBackupDataProcessor.pushData(TEST_DATA_1.length);
+        mFullBackupDataProcessor.handleSendBytesQuotaExceeded();
+
+        assertThat(ShadowEncryptedFullBackupTask.sCancelled).isTrue();
+    }
+
+    private void finishBackupTask() {
+        mExecutorService.runNext();
+    }
+
+    private void finishBackupTaskWithException(Exception exception) {
+        ShadowEncryptedFullBackupTask.sOnCallException = exception;
+        finishBackupTask();
+    }
+
+    @Implements(EncryptedFullBackupTask.class)
+    public static class ShadowEncryptedFullBackupTask {
+
+        private static InputStream sInputStream;
+        @Nullable private static Exception sOnCallException;
+        private static boolean sCancelled;
+
+        public void __constructor__(
+                ProtoStore<ChunksMetadataProto.ChunkListing> chunkListingStore,
+                TertiaryKeyManager tertiaryKeyManager,
+                EncryptedBackupTask task,
+                InputStream inputStream,
+                String packageName,
+                SecureRandom secureRandom) {
+            sInputStream = inputStream;
+        }
+
+        @Implementation
+        public Void call() throws Exception {
+            if (sOnCallException != null) {
+                throw sOnCallException;
+            }
+
+            return null;
+        }
+
+        @Implementation
+        public void cancel() {
+            sCancelled = true;
+        }
+
+        public static void reset() {
+            sOnCallException = null;
+            sCancelled = false;
+        }
+    }
+}
diff --git a/packages/BackupEncryption/test/robolectric/src/com/android/server/backup/encryption/tasks/EncryptedKvBackupTaskTest.java b/packages/BackupEncryption/test/robolectric/src/com/android/server/backup/encryption/tasks/EncryptedKvBackupTaskTest.java
new file mode 100644
index 0000000..fa4fef5
--- /dev/null
+++ b/packages/BackupEncryption/test/robolectric/src/com/android/server/backup/encryption/tasks/EncryptedKvBackupTaskTest.java
@@ -0,0 +1,356 @@
+/*
+ * 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.tasks;
+
+import static com.google.common.truth.Truth.assertThat;
+import static com.google.common.truth.Truth.assertWithMessage;
+
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.Matchers.eq;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+import static org.testng.Assert.assertFalse;
+import static org.testng.Assert.assertThrows;
+
+import android.app.Application;
+import android.util.Pair;
+
+import androidx.test.core.app.ApplicationProvider;
+
+import com.android.server.backup.encryption.chunk.ChunkHash;
+import com.android.server.backup.encryption.chunking.ProtoStore;
+import com.android.server.backup.encryption.keys.RecoverableKeyStoreSecondaryKey;
+import com.android.server.backup.encryption.keys.TertiaryKeyManager;
+import com.android.server.backup.encryption.kv.KeyValueListingBuilder;
+import com.android.server.backup.encryption.protos.nano.ChunksMetadataProto;
+import com.android.server.backup.encryption.protos.nano.KeyValueListingProto;
+import com.android.server.backup.encryption.protos.nano.WrappedKeyProto;
+import com.android.server.backup.testing.CryptoTestUtils;
+
+import java.io.IOException;
+import java.util.Arrays;
+import java.util.Map;
+import java.util.Map.Entry;
+
+import javax.crypto.SecretKey;
+
+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.ArgumentCaptor;
+import org.mockito.Captor;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+import org.robolectric.RobolectricTestRunner;
+
+@RunWith(RobolectricTestRunner.class)
+public class EncryptedKvBackupTaskTest {
+    private static final boolean INCREMENTAL = true;
+    private static final boolean NON_INCREMENTAL = false;
+
+    private static final String TEST_PACKAGE_1 = "com.example.app1";
+    private static final String TEST_KEY_1 = "key_1";
+    private static final String TEST_KEY_2 = "key_2";
+    private static final ChunkHash TEST_HASH_1 =
+            new ChunkHash(Arrays.copyOf(new byte[] {1}, ChunkHash.HASH_LENGTH_BYTES));
+    private static final ChunkHash TEST_HASH_2 =
+            new ChunkHash(Arrays.copyOf(new byte[] {2}, ChunkHash.HASH_LENGTH_BYTES));
+    private static final int TEST_LENGTH_1 = 200;
+    private static final int TEST_LENGTH_2 = 300;
+
+    @Rule public TemporaryFolder mTemporaryFolder = new TemporaryFolder();
+
+    @Captor private ArgumentCaptor<ChunksMetadataProto.ChunkListing> mChunkListingCaptor;
+
+    @Mock private TertiaryKeyManager mTertiaryKeyManager;
+    @Mock private RecoverableKeyStoreSecondaryKey mSecondaryKey;
+    @Mock private ProtoStore<KeyValueListingProto.KeyValueListing> mKeyValueListingStore;
+    @Mock private ProtoStore<ChunksMetadataProto.ChunkListing> mChunkListingStore;
+    @Mock private KvBackupEncrypter mKvBackupEncrypter;
+    @Mock private EncryptedBackupTask mEncryptedBackupTask;
+    @Mock private SecretKey mTertiaryKey;
+
+    private WrappedKeyProto.WrappedKey mWrappedTertiaryKey;
+    private KeyValueListingProto.KeyValueListing mNewKeyValueListing;
+    private ChunksMetadataProto.ChunkListing mNewChunkListing;
+    private EncryptedKvBackupTask mTask;
+
+    @Before
+    public void setUp() throws Exception {
+        MockitoAnnotations.initMocks(this);
+
+        Application application = ApplicationProvider.getApplicationContext();
+        mKeyValueListingStore = ProtoStore.createKeyValueListingStore(application);
+        mChunkListingStore = ProtoStore.createChunkListingStore(application);
+
+        mWrappedTertiaryKey = new WrappedKeyProto.WrappedKey();
+
+        when(mTertiaryKeyManager.wasKeyRotated()).thenReturn(false);
+        when(mTertiaryKeyManager.getKey()).thenReturn(mTertiaryKey);
+        when(mTertiaryKeyManager.getWrappedKey()).thenReturn(mWrappedTertiaryKey);
+
+        mNewKeyValueListing =
+                createKeyValueListing(
+                        CryptoTestUtils.mapOf(
+                                new Pair<>(TEST_KEY_1, TEST_HASH_1),
+                                new Pair<>(TEST_KEY_2, TEST_HASH_2)));
+        mNewChunkListing =
+                createChunkListing(
+                        CryptoTestUtils.mapOf(
+                                new Pair<>(TEST_HASH_1, TEST_LENGTH_1),
+                                new Pair<>(TEST_HASH_2, TEST_LENGTH_2)));
+        when(mKvBackupEncrypter.getNewKeyValueListing()).thenReturn(mNewKeyValueListing);
+        when(mEncryptedBackupTask.performIncrementalBackup(
+                        eq(mTertiaryKey), eq(mWrappedTertiaryKey), any()))
+                .thenReturn(mNewChunkListing);
+        when(mEncryptedBackupTask.performNonIncrementalBackup(
+                        eq(mTertiaryKey), eq(mWrappedTertiaryKey), any()))
+                .thenReturn(mNewChunkListing);
+
+        mTask =
+                new EncryptedKvBackupTask(
+                        mTertiaryKeyManager,
+                        mKeyValueListingStore,
+                        mSecondaryKey,
+                        mChunkListingStore,
+                        mKvBackupEncrypter,
+                        mEncryptedBackupTask,
+                        TEST_PACKAGE_1);
+    }
+
+    @Test
+    public void testPerformBackup_rotationRequired_deletesListings() throws Exception {
+        mKeyValueListingStore.saveProto(
+                TEST_PACKAGE_1,
+                createKeyValueListing(CryptoTestUtils.mapOf(new Pair<>(TEST_KEY_1, TEST_HASH_1))));
+        mChunkListingStore.saveProto(
+                TEST_PACKAGE_1,
+                createChunkListing(CryptoTestUtils.mapOf(new Pair<>(TEST_HASH_1, TEST_LENGTH_1))));
+
+        when(mTertiaryKeyManager.wasKeyRotated()).thenReturn(true);
+        // Throw an IOException so it aborts before saving the new listings.
+        when(mEncryptedBackupTask.performNonIncrementalBackup(any(), any(), any()))
+                .thenThrow(IOException.class);
+
+        assertThrows(IOException.class, () -> mTask.performBackup(NON_INCREMENTAL));
+
+        assertFalse(mKeyValueListingStore.loadProto(TEST_PACKAGE_1).isPresent());
+        assertFalse(mChunkListingStore.loadProto(TEST_PACKAGE_1).isPresent());
+    }
+
+    @Test
+    public void testPerformBackup_rotationRequiredButIncremental_throws() throws Exception {
+        mKeyValueListingStore.saveProto(
+                TEST_PACKAGE_1,
+                createKeyValueListing(CryptoTestUtils.mapOf(new Pair<>(TEST_KEY_1, TEST_HASH_1))));
+        mChunkListingStore.saveProto(
+                TEST_PACKAGE_1,
+                createChunkListing(CryptoTestUtils.mapOf(new Pair<>(TEST_HASH_1, TEST_LENGTH_1))));
+
+        when(mTertiaryKeyManager.wasKeyRotated()).thenReturn(true);
+
+        assertThrows(NonIncrementalBackupRequiredException.class,
+                () -> mTask.performBackup(INCREMENTAL));
+    }
+
+    @Test
+    public void testPerformBackup_rotationRequiredAndNonIncremental_performsNonIncrementalBackup()
+            throws Exception {
+        mKeyValueListingStore.saveProto(
+                TEST_PACKAGE_1,
+                createKeyValueListing(CryptoTestUtils.mapOf(new Pair<>(TEST_KEY_1, TEST_HASH_1))));
+        mChunkListingStore.saveProto(
+                TEST_PACKAGE_1,
+                createChunkListing(CryptoTestUtils.mapOf(new Pair<>(TEST_HASH_1, TEST_LENGTH_1))));
+
+        when(mTertiaryKeyManager.wasKeyRotated()).thenReturn(true);
+
+        mTask.performBackup(NON_INCREMENTAL);
+
+        verify(mEncryptedBackupTask)
+                .performNonIncrementalBackup(eq(mTertiaryKey), eq(mWrappedTertiaryKey), any());
+    }
+
+    @Test
+    public void testPerformBackup_existingStateButNonIncremental_deletesListings() throws Exception {
+        mKeyValueListingStore.saveProto(
+                TEST_PACKAGE_1,
+                createKeyValueListing(CryptoTestUtils.mapOf(new Pair<>(TEST_KEY_1, TEST_HASH_1))));
+        mChunkListingStore.saveProto(
+                TEST_PACKAGE_1,
+                createChunkListing(CryptoTestUtils.mapOf(new Pair<>(TEST_HASH_1, TEST_LENGTH_1))));
+
+        // Throw an IOException so it aborts before saving the new listings.
+        when(mEncryptedBackupTask.performNonIncrementalBackup(any(), any(), any()))
+                .thenThrow(IOException.class);
+
+        assertThrows(IOException.class, () -> mTask.performBackup(NON_INCREMENTAL));
+
+        assertFalse(mKeyValueListingStore.loadProto(TEST_PACKAGE_1).isPresent());
+        assertFalse(mChunkListingStore.loadProto(TEST_PACKAGE_1).isPresent());
+    }
+
+    @Test
+    public void testPerformBackup_keyValueListingMissing_deletesChunkListingAndPerformsNonIncremental()
+            throws Exception {
+        mChunkListingStore.saveProto(
+                TEST_PACKAGE_1,
+                createChunkListing(CryptoTestUtils.mapOf(new Pair<>(TEST_HASH_1, TEST_LENGTH_1))));
+
+        // Throw an IOException so it aborts before saving the new listings.
+        when(mEncryptedBackupTask.performNonIncrementalBackup(any(), any(), any()))
+                .thenThrow(IOException.class);
+
+        assertThrows(IOException.class, () -> mTask.performBackup(NON_INCREMENTAL));
+
+        verify(mEncryptedBackupTask).performNonIncrementalBackup(any(), any(), any());
+        assertFalse(mKeyValueListingStore.loadProto(TEST_PACKAGE_1).isPresent());
+        assertFalse(mChunkListingStore.loadProto(TEST_PACKAGE_1).isPresent());
+    }
+
+    @Test
+    public void testPerformBackup_chunkListingMissing_deletesKeyValueListingAndPerformsNonIncremental()
+            throws Exception {
+        mKeyValueListingStore.saveProto(
+                TEST_PACKAGE_1,
+                createKeyValueListing(CryptoTestUtils.mapOf(new Pair<>(TEST_KEY_1, TEST_HASH_1))));
+
+        // Throw an IOException so it aborts before saving the new listings.
+        when(mEncryptedBackupTask.performNonIncrementalBackup(any(), any(), any()))
+                .thenThrow(IOException.class);
+
+        assertThrows(IOException.class, () -> mTask.performBackup(NON_INCREMENTAL));
+
+        verify(mEncryptedBackupTask).performNonIncrementalBackup(any(), any(), any());
+        assertFalse(mKeyValueListingStore.loadProto(TEST_PACKAGE_1).isPresent());
+        assertFalse(mChunkListingStore.loadProto(TEST_PACKAGE_1).isPresent());
+    }
+
+    @Test
+    public void testPerformBackup_existingStateAndIncremental_performsIncrementalBackup()
+            throws Exception {
+        mKeyValueListingStore.saveProto(
+                TEST_PACKAGE_1,
+                createKeyValueListing(CryptoTestUtils.mapOf(new Pair<>(TEST_KEY_1, TEST_HASH_1))));
+        ChunksMetadataProto.ChunkListing oldChunkListing =
+                createChunkListing(CryptoTestUtils.mapOf(new Pair<>(TEST_HASH_1, TEST_LENGTH_1)));
+        mChunkListingStore.saveProto(TEST_PACKAGE_1, oldChunkListing);
+
+        mTask.performBackup(INCREMENTAL);
+
+        verify(mEncryptedBackupTask)
+                .performIncrementalBackup(
+                        eq(mTertiaryKey), eq(mWrappedTertiaryKey), mChunkListingCaptor.capture());
+        assertChunkListingsEqual(mChunkListingCaptor.getValue(), oldChunkListing);
+    }
+
+    @Test
+    public void testPerformBackup_noExistingStateAndNonIncremental_performsNonIncrementalBackup()
+            throws Exception {
+        mTask.performBackup(NON_INCREMENTAL);
+
+        verify(mEncryptedBackupTask)
+                .performNonIncrementalBackup(eq(mTertiaryKey), eq(mWrappedTertiaryKey), eq(null));
+    }
+
+    @Test
+    public void testPerformBackup_incremental_savesNewListings() throws Exception {
+        mKeyValueListingStore.saveProto(
+                TEST_PACKAGE_1,
+                createKeyValueListing(CryptoTestUtils.mapOf(new Pair<>(TEST_KEY_1, TEST_HASH_1))));
+        mChunkListingStore.saveProto(
+                TEST_PACKAGE_1,
+                createChunkListing(CryptoTestUtils.mapOf(new Pair<>(TEST_HASH_1, TEST_LENGTH_1))));
+
+        mTask.performBackup(INCREMENTAL);
+
+        KeyValueListingProto.KeyValueListing actualKeyValueListing =
+                mKeyValueListingStore.loadProto(TEST_PACKAGE_1).get();
+        ChunksMetadataProto.ChunkListing actualChunkListing =
+                mChunkListingStore.loadProto(TEST_PACKAGE_1).get();
+        assertKeyValueListingsEqual(actualKeyValueListing, mNewKeyValueListing);
+        assertChunkListingsEqual(actualChunkListing, mNewChunkListing);
+    }
+
+    @Test
+    public void testPerformBackup_nonIncremental_savesNewListings() throws Exception {
+        mTask.performBackup(NON_INCREMENTAL);
+
+        KeyValueListingProto.KeyValueListing actualKeyValueListing =
+                mKeyValueListingStore.loadProto(TEST_PACKAGE_1).get();
+        ChunksMetadataProto.ChunkListing actualChunkListing =
+                mChunkListingStore.loadProto(TEST_PACKAGE_1).get();
+        assertKeyValueListingsEqual(actualKeyValueListing, mNewKeyValueListing);
+        assertChunkListingsEqual(actualChunkListing, mNewChunkListing);
+    }
+
+    private static KeyValueListingProto.KeyValueListing createKeyValueListing(
+            Map<String, ChunkHash> pairs) {
+        return new KeyValueListingBuilder().addAll(pairs).build();
+    }
+
+    private static ChunksMetadataProto.ChunkListing createChunkListing(
+            Map<ChunkHash, Integer> chunks) {
+        ChunksMetadataProto.Chunk[] listingChunks = new ChunksMetadataProto.Chunk[chunks.size()];
+        int chunksAdded = 0;
+        for (Entry<ChunkHash, Integer> entry : chunks.entrySet()) {
+            listingChunks[chunksAdded] = CryptoTestUtils.newChunk(entry.getKey(), entry.getValue());
+            chunksAdded++;
+        }
+        return CryptoTestUtils.newChunkListingWithoutDocId(
+                /* fingerprintSalt */ new byte[0],
+                ChunksMetadataProto.AES_256_GCM,
+                ChunksMetadataProto.CHUNK_ORDERING_TYPE_UNSPECIFIED,
+                listingChunks);
+    }
+
+    private static void assertKeyValueListingsEqual(
+            KeyValueListingProto.KeyValueListing actual,
+            KeyValueListingProto.KeyValueListing expected) {
+        KeyValueListingProto.KeyValueEntry[] actualEntries = actual.entries;
+        KeyValueListingProto.KeyValueEntry[] expectedEntries = expected.entries;
+        assertThat(actualEntries.length).isEqualTo(expectedEntries.length);
+        for (int i = 0; i < actualEntries.length; i++) {
+            assertWithMessage("entry " + i)
+                    .that(actualEntries[i].key)
+                    .isEqualTo(expectedEntries[i].key);
+            assertWithMessage("entry " + i)
+                    .that(actualEntries[i].hash)
+                    .isEqualTo(expectedEntries[i].hash);
+        }
+    }
+
+    private static void assertChunkListingsEqual(
+            ChunksMetadataProto.ChunkListing actual, ChunksMetadataProto.ChunkListing expected) {
+        ChunksMetadataProto.Chunk[] actualChunks = actual.chunks;
+        ChunksMetadataProto.Chunk[] expectedChunks = expected.chunks;
+        assertThat(actualChunks.length).isEqualTo(expectedChunks.length);
+        for (int i = 0; i < actualChunks.length; i++) {
+            assertWithMessage("chunk " + i)
+                    .that(actualChunks[i].hash)
+                    .isEqualTo(expectedChunks[i].hash);
+            assertWithMessage("chunk " + i)
+                    .that(actualChunks[i].length)
+                    .isEqualTo(expectedChunks[i].length);
+        }
+        assertThat(actual.cipherType).isEqualTo(expected.cipherType);
+        assertThat(actual.documentId)
+                .isEqualTo(expected.documentId == null ? "" : expected.documentId);
+    }
+}
diff --git a/packages/BackupEncryption/test/robolectric/src/com/android/server/backup/encryption/tasks/EncryptedKvRestoreTaskTest.java b/packages/BackupEncryption/test/robolectric/src/com/android/server/backup/encryption/tasks/EncryptedKvRestoreTaskTest.java
new file mode 100644
index 0000000..6666d95
--- /dev/null
+++ b/packages/BackupEncryption/test/robolectric/src/com/android/server/backup/encryption/tasks/EncryptedKvRestoreTaskTest.java
@@ -0,0 +1,185 @@
+/*
+ * 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.tasks;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.Mockito.doAnswer;
+import static org.mockito.Mockito.doThrow;
+import static org.mockito.Mockito.when;
+import static org.testng.Assert.assertThrows;
+
+import android.os.ParcelFileDescriptor;
+
+import com.android.server.backup.encryption.chunk.ChunkHash;
+import com.android.server.backup.encryption.chunking.ChunkHasher;
+import com.android.server.backup.testing.CryptoTestUtils;
+import com.android.server.testing.shadows.DataEntity;
+import com.android.server.testing.shadows.ShadowBackupDataOutput;
+
+import com.google.protobuf.nano.MessageNano;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.ObjectInputStream;
+import java.io.ObjectOutputStream;
+import java.security.InvalidKeyException;
+import java.security.NoSuchAlgorithmException;
+import java.util.Arrays;
+import java.util.HashSet;
+import java.util.Set;
+
+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 org.robolectric.RobolectricTestRunner;
+import org.robolectric.annotation.Config;
+
+@Config(shadows = {ShadowBackupDataOutput.class})
+@RunWith(RobolectricTestRunner.class)
+public class EncryptedKvRestoreTaskTest {
+    private static final String TEST_KEY_1 = "test_key_1";
+    private static final String TEST_KEY_2 = "test_key_2";
+    private static final String TEST_KEY_3 = "test_key_3";
+    private static final byte[] TEST_VALUE_1 = {1, 2, 3};
+    private static final byte[] TEST_VALUE_2 = {4, 5, 6};
+    private static final byte[] TEST_VALUE_3 = {20, 25, 30, 35};
+
+    @Rule public TemporaryFolder temporaryFolder = new TemporaryFolder();
+
+    private File temporaryDirectory;
+
+    @Mock private ParcelFileDescriptor mParcelFileDescriptor;
+    @Mock private ChunkHasher mChunkHasher;
+    @Mock private FullRestoreToFileTask mFullRestoreToFileTask;
+    @Mock private BackupFileDecryptorTask mBackupFileDecryptorTask;
+
+    private EncryptedKvRestoreTask task;
+
+    @Before
+    public void setUp() throws Exception {
+        MockitoAnnotations.initMocks(this);
+
+        when(mChunkHasher.computeHash(any()))
+                .thenAnswer(invocation -> fakeHash(invocation.getArgument(0)));
+        doAnswer(invocation -> writeTestPairsToFile(invocation.getArgument(0)))
+                .when(mFullRestoreToFileTask)
+                .restoreToFile(any());
+        doAnswer(
+                        invocation ->
+                                readPairsFromFile(
+                                        invocation.getArgument(0), invocation.getArgument(1)))
+                .when(mBackupFileDecryptorTask)
+                .decryptFile(any(), any());
+
+        temporaryDirectory = temporaryFolder.newFolder();
+        task =
+                new EncryptedKvRestoreTask(
+                        temporaryDirectory,
+                        mChunkHasher,
+                        mFullRestoreToFileTask,
+                        mBackupFileDecryptorTask);
+    }
+
+    @Test
+    public void testGetRestoreData_writesPairsToOutputInOrder() throws Exception {
+        task.getRestoreData(mParcelFileDescriptor);
+
+        assertThat(ShadowBackupDataOutput.getEntities())
+                .containsExactly(
+                        new DataEntity(TEST_KEY_1, TEST_VALUE_1),
+                        new DataEntity(TEST_KEY_2, TEST_VALUE_2),
+                        new DataEntity(TEST_KEY_3, TEST_VALUE_3))
+                .inOrder();
+    }
+
+    @Test
+    public void testGetRestoreData_exceptionDuringDecryption_throws() throws Exception {
+        doThrow(IOException.class).when(mBackupFileDecryptorTask).decryptFile(any(), any());
+        assertThrows(IOException.class, () -> task.getRestoreData(mParcelFileDescriptor));
+    }
+
+    @Test
+    public void testGetRestoreData_exceptionDuringDownload_throws() throws Exception {
+        doThrow(IOException.class).when(mFullRestoreToFileTask).restoreToFile(any());
+        assertThrows(IOException.class, () -> task.getRestoreData(mParcelFileDescriptor));
+    }
+
+    @Test
+    public void testGetRestoreData_exceptionDuringDecryption_deletesTemporaryFiles() throws Exception {
+        doThrow(InvalidKeyException.class).when(mBackupFileDecryptorTask).decryptFile(any(), any());
+        assertThrows(InvalidKeyException.class, () -> task.getRestoreData(mParcelFileDescriptor));
+        assertThat(temporaryDirectory.listFiles()).isEmpty();
+    }
+
+    @Test
+    public void testGetRestoreData_exceptionDuringDownload_deletesTemporaryFiles() throws Exception {
+        doThrow(IOException.class).when(mFullRestoreToFileTask).restoreToFile(any());
+        assertThrows(IOException.class, () -> task.getRestoreData(mParcelFileDescriptor));
+        assertThat(temporaryDirectory.listFiles()).isEmpty();
+    }
+
+    private static Void writeTestPairsToFile(File file) throws IOException {
+        // Write the pairs out of order to check the task sorts them.
+        Set<byte[]> pairs =
+                new HashSet<>(
+                        Arrays.asList(
+                                createPair(TEST_KEY_1, TEST_VALUE_1),
+                                createPair(TEST_KEY_3, TEST_VALUE_3),
+                                createPair(TEST_KEY_2, TEST_VALUE_2)));
+
+        try (ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream(file))) {
+            oos.writeObject(pairs);
+        }
+        return null;
+    }
+
+    private static Void readPairsFromFile(File file, DecryptedChunkOutput decryptedChunkOutput)
+            throws IOException, ClassNotFoundException, InvalidKeyException,
+                    NoSuchAlgorithmException {
+        try (ObjectInputStream ois = new ObjectInputStream(new FileInputStream(file));
+                DecryptedChunkOutput output = decryptedChunkOutput.open()) {
+            Set<byte[]> pairs = readPairs(ois);
+            for (byte[] pair : pairs) {
+                output.processChunk(pair, pair.length);
+            }
+        }
+
+        return null;
+    }
+
+    private static byte[] createPair(String key, byte[] value) {
+        return MessageNano.toByteArray(CryptoTestUtils.newPair(key, value));
+    }
+
+    @SuppressWarnings("unchecked") // deserialization.
+    private static Set<byte[]> readPairs(ObjectInputStream ois)
+            throws IOException, ClassNotFoundException {
+        return (Set<byte[]>) ois.readObject();
+    }
+
+    private static ChunkHash fakeHash(byte[] data) {
+        return new ChunkHash(Arrays.copyOf(data, ChunkHash.HASH_LENGTH_BYTES));
+    }
+}
diff --git a/packages/BackupEncryption/test/robolectric/src/com/android/server/backup/encryption/testing/QueuingNonAutomaticExecutorService.java b/packages/BackupEncryption/test/robolectric/src/com/android/server/backup/encryption/testing/QueuingNonAutomaticExecutorService.java
new file mode 100644
index 0000000..9d2272e
--- /dev/null
+++ b/packages/BackupEncryption/test/robolectric/src/com/android/server/backup/encryption/testing/QueuingNonAutomaticExecutorService.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.server.backup.encryption.testing;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.concurrent.AbstractExecutorService;
+import java.util.concurrent.TimeUnit;
+
+/**
+ * ExecutorService which needs to be stepped through the jobs in its' queue.
+ *
+ * <p>This is a deliberately simple implementation because it's only used in testing. The queued
+ * jobs are run on the main thread to eliminate any race condition bugs.
+ */
+public class QueuingNonAutomaticExecutorService extends AbstractExecutorService {
+
+    private List<Runnable> mWaitingJobs = new ArrayList<>();
+    private int mWaitingJobCount = 0;
+
+    @Override
+    public void shutdown() {
+        mWaitingJobCount = mWaitingJobs.size();
+        mWaitingJobs = null; // This will force an error if jobs are submitted after shutdown
+    }
+
+    @Override
+    public List<Runnable> shutdownNow() {
+        List<Runnable> queuedJobs = mWaitingJobs;
+        shutdown();
+        return queuedJobs;
+    }
+
+    @Override
+    public boolean isShutdown() {
+        return mWaitingJobs == null;
+    }
+
+    @Override
+    public boolean isTerminated() {
+        return mWaitingJobs == null && mWaitingJobCount == 0;
+    }
+
+    @Override
+    public boolean awaitTermination(long timeout, TimeUnit unit) throws InterruptedException {
+        long expiry = System.currentTimeMillis() + unit.toMillis(timeout);
+        for (Runnable job : mWaitingJobs) {
+            if (System.currentTimeMillis() > expiry) {
+                return false;
+            }
+
+            job.run();
+        }
+        return true;
+    }
+
+    @Override
+    public void execute(Runnable command) {
+        mWaitingJobs.add(command);
+    }
+
+    public void runNext() {
+        if (mWaitingJobs.isEmpty()) {
+            throw new IllegalStateException("Attempted to run jobs on an empty paused executor");
+        }
+
+        mWaitingJobs.remove(0).run();
+    }
+}
diff --git a/packages/BackupEncryption/test/robolectric/src/com/android/server/testing/CryptoTestUtils.java b/packages/BackupEncryption/test/robolectric/src/com/android/server/testing/CryptoTestUtils.java
index 5dfd5ee..b0c02ba 100644
--- a/packages/BackupEncryption/test/robolectric/src/com/android/server/testing/CryptoTestUtils.java
+++ b/packages/BackupEncryption/test/robolectric/src/com/android/server/testing/CryptoTestUtils.java
@@ -16,6 +16,8 @@
 
 package com.android.server.backup.testing;
 
+import android.util.Pair;
+
 import com.android.server.backup.encryption.chunk.ChunkHash;
 import com.android.server.backup.encryption.protos.nano.ChunksMetadataProto;
 import com.android.server.backup.encryption.protos.nano.KeyValuePairProto;
@@ -23,6 +25,8 @@
 import java.nio.charset.Charset;
 import java.security.NoSuchAlgorithmException;
 import java.util.Arrays;
+import java.util.HashMap;
+import java.util.Map;
 import java.util.Random;
 
 import javax.crypto.KeyGenerator;
@@ -162,4 +166,12 @@
         clone.checksum = Arrays.copyOf(original.checksum, original.checksum.length);
         return clone;
     }
+
+    public static <K, V> Map<K, V> mapOf(Pair<K, V>... pairs) {
+        Map<K, V> map = new HashMap<>();
+        for (Pair<K, V> pair : pairs) {
+            map.put(pair.first, pair.second);
+        }
+        return map;
+    }
 }
diff --git a/packages/BackupEncryption/test/robolectric/src/com/android/server/testing/shadows/ShadowBackupDataOutput.java b/packages/BackupEncryption/test/robolectric/src/com/android/server/testing/shadows/ShadowBackupDataOutput.java
new file mode 100644
index 0000000..2302e55
--- /dev/null
+++ b/packages/BackupEncryption/test/robolectric/src/com/android/server/testing/shadows/ShadowBackupDataOutput.java
@@ -0,0 +1,66 @@
+/*
+ * 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.testing.shadows;
+
+import android.app.backup.BackupDataOutput;
+
+import java.io.FileDescriptor;
+import java.util.ArrayList;
+import java.util.LinkedHashSet;
+import java.util.List;
+import java.util.Set;
+
+import org.junit.Assert;
+import org.robolectric.annotation.Implementation;
+import org.robolectric.annotation.Implements;
+
+/** Shadow for BackupDataOutput. */
+@Implements(BackupDataOutput.class)
+public class ShadowBackupDataOutput {
+    private static final List<DataEntity> ENTRIES = new ArrayList<>();
+
+    private String mCurrentKey;
+    private int mDataSize;
+
+    public static void reset() {
+        ENTRIES.clear();
+    }
+
+    public static Set<DataEntity> getEntities() {
+        return new LinkedHashSet<>(ENTRIES);
+    }
+
+    public void __constructor__(FileDescriptor fd) {}
+
+    public void __constructor__(FileDescriptor fd, long quota) {}
+
+    public void __constructor__(FileDescriptor fd, long quota, int transportFlags) {}
+
+    @Implementation
+    public int writeEntityHeader(String key, int size) {
+        mCurrentKey = key;
+        mDataSize = size;
+        return 0;
+    }
+
+    @Implementation
+    public int writeEntityData(byte[] data, int size) {
+        Assert.assertEquals("ShadowBackupDataOutput expects size = mDataSize", size, mDataSize);
+        ENTRIES.add(new DataEntity(mCurrentKey, data, mDataSize));
+        return 0;
+    }
+}
diff --git a/packages/BackupRestoreConfirmation/res/values-fi/strings.xml b/packages/BackupRestoreConfirmation/res/values-fi/strings.xml
index 4517410..bc9dbde 100644
--- a/packages/BackupRestoreConfirmation/res/values-fi/strings.xml
+++ b/packages/BackupRestoreConfirmation/res/values-fi/strings.xml
@@ -27,7 +27,7 @@
     <string name="current_password_text" msgid="8268189555578298067">"Kirjoita nykyinen varmuuskopioinnin salasana alla:"</string>
     <string name="device_encryption_restore_text" msgid="1570864916855208992">"Kirjoita laitteen salauksen salasana alle."</string>
     <string name="device_encryption_backup_text" msgid="5866590762672844664">"Kirjoita laitteen salauksen salasana alle. Salasanaa käytetään myös varmuuskopioarkiston salaamiseen."</string>
-    <string name="backup_enc_password_text" msgid="4981585714795233099">"Anna salasana kaikkien varmuuskopiotietojen salaamiseksi. Jos tämä jätetään tyhjäksi, nykyistä varmuuskopioinnin salasanaa käytetään:"</string>
+    <string name="backup_enc_password_text" msgid="4981585714795233099">"Lisää salasana kaikkien varmuuskopiotietojen salaamiseksi. Jos tämä jätetään tyhjäksi, nykyistä varmuuskopioinnin salasanaa käytetään:"</string>
     <string name="backup_enc_password_optional" msgid="1350137345907579306">"Jos haluat salata kaikki varmuuskopiotiedot, kirjoita salasana alle:"</string>
     <string name="backup_enc_password_required" msgid="7889652203371654149">"Koska laite on salattu, myös varmuuskopiointi on salattava. Kirjoita salasana alle:"</string>
     <string name="restore_enc_password_text" msgid="6140898525580710823">"Jos palautustiedot on salattu, anna salasana alla:"</string>
diff --git a/packages/CarSystemUI/res/layout/super_status_bar.xml b/packages/CarSystemUI/res/layout/super_status_bar.xml
index e1bcc2e..08d48bf 100644
--- a/packages/CarSystemUI/res/layout/super_status_bar.xml
+++ b/packages/CarSystemUI/res/layout/super_status_bar.xml
@@ -93,7 +93,7 @@
         android:layout_height="match_parent"
         android:visibility="invisible"/>
 
-    <include layout="@layout/status_bar_expanded"
+    <ViewStub android:id="@+id/status_bar_expanded"
         android:layout_width="match_parent"
         android:layout_height="match_parent"
         android:visibility="invisible"/>
diff --git a/packages/CarSystemUI/src/com/android/systemui/CarSystemUIFactory.java b/packages/CarSystemUI/src/com/android/systemui/CarSystemUIFactory.java
index c7654e8..be2d542 100644
--- a/packages/CarSystemUI/src/com/android/systemui/CarSystemUIFactory.java
+++ b/packages/CarSystemUI/src/com/android/systemui/CarSystemUIFactory.java
@@ -23,8 +23,6 @@
 import com.android.systemui.statusbar.car.CarFacetButtonController;
 import com.android.systemui.statusbar.car.CarStatusBarKeyguardViewManager;
 import com.android.systemui.statusbar.phone.StatusBarKeyguardViewManager;
-import com.android.systemui.volume.CarVolumeDialogComponent;
-import com.android.systemui.volume.VolumeDialogComponent;
 
 import javax.inject.Singleton;
 
@@ -57,10 +55,6 @@
         return new CarStatusBarKeyguardViewManager(context, viewMediatorCallback, lockPatternUtils);
     }
 
-    public VolumeDialogComponent createVolumeDialogComponent(SystemUI systemUi, Context context) {
-        return new CarVolumeDialogComponent(systemUi, context);
-    }
-
     @Singleton
     @Component(modules = ContextHolder.class)
     public interface CarDependencyComponent {
diff --git a/packages/CarSystemUI/src/com/android/systemui/CarSystemUIModule.java b/packages/CarSystemUI/src/com/android/systemui/CarSystemUIModule.java
index 9a063aa..b1067f8 100644
--- a/packages/CarSystemUI/src/com/android/systemui/CarSystemUIModule.java
+++ b/packages/CarSystemUI/src/com/android/systemui/CarSystemUIModule.java
@@ -29,12 +29,15 @@
 import com.android.systemui.power.EnhancedEstimatesImpl;
 import com.android.systemui.statusbar.NotificationLockscreenUserManager;
 import com.android.systemui.statusbar.NotificationLockscreenUserManagerImpl;
+import com.android.systemui.statusbar.car.CarStatusBar;
 import com.android.systemui.statusbar.notification.NotificationEntryManager;
 import com.android.systemui.statusbar.notification.NotificationInterruptionStateProvider;
 import com.android.systemui.statusbar.notification.collection.NotificationData;
 import com.android.systemui.statusbar.phone.KeyguardEnvironmentImpl;
 import com.android.systemui.statusbar.phone.ShadeController;
 import com.android.systemui.statusbar.phone.StatusBar;
+import com.android.systemui.volume.CarVolumeDialogComponent;
+import com.android.systemui.volume.VolumeDialogComponent;
 
 import javax.inject.Named;
 import javax.inject.Singleton;
@@ -42,6 +45,8 @@
 import dagger.Binds;
 import dagger.Module;
 import dagger.Provides;
+import dagger.multibindings.ClassKey;
+import dagger.multibindings.IntoMap;
 
 @Module
 abstract class CarSystemUIModule {
@@ -94,4 +99,13 @@
     @Binds
     abstract SystemUIRootComponent bindSystemUIRootComponent(
             CarSystemUIRootComponent systemUIRootComponent);
+
+    @Binds
+    @IntoMap
+    @ClassKey(StatusBar.class)
+    public abstract SystemUI providesStatusBar(CarStatusBar statusBar);
+
+    @Binds
+    abstract VolumeDialogComponent bindVolumeDialogComponent(
+            CarVolumeDialogComponent carVolumeDialogComponent);
 }
diff --git a/packages/CarSystemUI/src/com/android/systemui/car/CarNotificationEntryManager.java b/packages/CarSystemUI/src/com/android/systemui/car/CarNotificationEntryManager.java
index a107dd7..53a88a9 100644
--- a/packages/CarSystemUI/src/com/android/systemui/car/CarNotificationEntryManager.java
+++ b/packages/CarSystemUI/src/com/android/systemui/car/CarNotificationEntryManager.java
@@ -15,11 +15,12 @@
  */
 package com.android.systemui.car;
 
-import android.content.Context;
 import android.service.notification.NotificationListenerService;
 import android.service.notification.StatusBarNotification;
 
 import com.android.systemui.statusbar.notification.NotificationEntryManager;
+import com.android.systemui.statusbar.notification.collection.NotificationData;
+import com.android.systemui.statusbar.notification.logging.NotifLog;
 
 import javax.inject.Inject;
 import javax.inject.Singleton;
@@ -34,8 +35,8 @@
 public class CarNotificationEntryManager extends NotificationEntryManager {
 
     @Inject
-    public CarNotificationEntryManager(Context context) {
-        super(context);
+    public CarNotificationEntryManager(NotificationData notificationData, NotifLog notifLog) {
+        super(notificationData, notifLog);
     }
 
     @Override
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 b0ab5b4..a585727 100644
--- a/packages/CarSystemUI/src/com/android/systemui/statusbar/car/CarStatusBar.java
+++ b/packages/CarSystemUI/src/com/android/systemui/statusbar/car/CarStatusBar.java
@@ -16,6 +16,8 @@
 
 package com.android.systemui.statusbar.car;
 
+import static com.android.systemui.Dependency.ALLOW_NOTIFICATION_LONG_PRESS_NAME;
+
 import android.animation.Animator;
 import android.animation.AnimatorListenerAdapter;
 import android.animation.ValueAnimator;
@@ -34,6 +36,7 @@
 import android.graphics.drawable.Drawable;
 import android.inputmethodservice.InputMethodService;
 import android.os.IBinder;
+import android.util.DisplayMetrics;
 import android.util.Log;
 import android.view.Display;
 import android.view.GestureDetector;
@@ -57,36 +60,85 @@
 import com.android.car.notification.NotificationDataManager;
 import com.android.car.notification.NotificationViewController;
 import com.android.car.notification.PreprocessingManager;
+import com.android.internal.logging.MetricsLogger;
 import com.android.internal.statusbar.RegisterStatusBarResult;
 import com.android.keyguard.KeyguardUpdateMonitor;
 import com.android.systemui.BatteryMeterView;
 import com.android.systemui.CarSystemUIFactory;
 import com.android.systemui.Dependency;
+import com.android.systemui.ForegroundServiceController;
 import com.android.systemui.Prefs;
 import com.android.systemui.R;
 import com.android.systemui.SystemUIFactory;
+import com.android.systemui.UiOffloadThread;
+import com.android.systemui.appops.AppOpsController;
+import com.android.systemui.assist.AssistManager;
+import com.android.systemui.broadcast.BroadcastDispatcher;
+import com.android.systemui.bubbles.BubbleController;
 import com.android.systemui.classifier.FalsingLog;
+import com.android.systemui.colorextraction.SysuiColorExtractor;
+import com.android.systemui.doze.DozeLog;
 import com.android.systemui.fragments.FragmentHostManager;
+import com.android.systemui.keyguard.KeyguardViewMediator;
 import com.android.systemui.keyguard.ScreenLifecycle;
+import com.android.systemui.keyguard.WakefulnessLifecycle;
 import com.android.systemui.plugins.FalsingManager;
 import com.android.systemui.plugins.qs.QS;
 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.FlingAnimationUtils;
+import com.android.systemui.statusbar.NavigationBarController;
+import com.android.systemui.statusbar.NotificationListener;
+import com.android.systemui.statusbar.NotificationLockscreenUserManager;
+import com.android.systemui.statusbar.NotificationMediaManager;
+import com.android.systemui.statusbar.NotificationRemoteInputManager;
+import com.android.systemui.statusbar.NotificationViewHierarchyManager;
+import com.android.systemui.statusbar.PulseExpansionHandler;
 import com.android.systemui.statusbar.StatusBarState;
+import com.android.systemui.statusbar.SysuiStatusBarStateController;
+import com.android.systemui.statusbar.VibratorHelper;
 import com.android.systemui.statusbar.car.hvac.HvacController;
 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.NotificationAlertingManager;
+import com.android.systemui.statusbar.notification.NotificationEntryManager;
+import com.android.systemui.statusbar.notification.NotificationInterruptionStateProvider;
+import com.android.systemui.statusbar.notification.NotificationWakeUpCoordinator;
+import com.android.systemui.statusbar.notification.VisualStabilityManager;
+import com.android.systemui.statusbar.notification.logging.NotifLog;
+import com.android.systemui.statusbar.notification.logging.NotificationLogger;
+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.HeadsUpManagerPhone;
+import com.android.systemui.statusbar.phone.KeyguardBypassController;
+import com.android.systemui.statusbar.phone.LightBarController;
+import com.android.systemui.statusbar.phone.NotificationGroupAlertTransferHelper;
+import com.android.systemui.statusbar.phone.NotificationGroupManager;
 import com.android.systemui.statusbar.phone.StatusBar;
+import com.android.systemui.statusbar.phone.StatusBarIconController;
+import com.android.systemui.statusbar.phone.StatusBarWindowController;
+import com.android.systemui.statusbar.phone.StatusBarWindowViewController;
 import com.android.systemui.statusbar.policy.BatteryController;
+import com.android.systemui.statusbar.policy.ConfigurationController;
 import com.android.systemui.statusbar.policy.DeviceProvisionedController;
+import com.android.systemui.statusbar.policy.KeyguardStateController;
+import com.android.systemui.statusbar.policy.NetworkController;
+import com.android.systemui.statusbar.policy.RemoteInputQuickSettingsDisabler;
 import com.android.systemui.statusbar.policy.UserSwitcherController;
+import com.android.systemui.statusbar.policy.ZenModeController;
+import com.android.systemui.util.InjectionInflationController;
 
 import java.io.FileDescriptor;
 import java.io.PrintWriter;
 import java.util.Map;
 
+import javax.inject.Inject;
+import javax.inject.Named;
+
 /**
  * A status bar (and navigation bar) tailored for the automotive use case.
  */
@@ -175,6 +227,8 @@
     private boolean mHideNavBarForKeyboard;
     private boolean mBottomNavBarVisible;
 
+    private final NavigationBarController mNavigationBarController;
+
     private final CarPowerStateListener mCarPowerStateListener =
             (int state) -> {
                 // When the car powers on, clear all notifications and mute/unread states.
@@ -189,6 +243,122 @@
                 }
             };
 
+    @Inject
+    public CarStatusBar(
+            Context context,
+            LightBarController lightBarController,
+            AutoHideController autoHideController,
+            KeyguardUpdateMonitor keyguardUpdateMonitor,
+            StatusBarIconController statusBarIconController,
+            DozeLog dozeLog,
+            InjectionInflationController injectionInflationController,
+            PulseExpansionHandler pulseExpansionHandler,
+            NotificationWakeUpCoordinator notificationWakeUpCoordinator,
+            KeyguardBypassController keyguardBypassController,
+            KeyguardStateController keyguardStateController,
+            HeadsUpManagerPhone headsUpManagerPhone,
+            DynamicPrivacyController dynamicPrivacyController,
+            BypassHeadsUpNotifier bypassHeadsUpNotifier,
+            @Named(ALLOW_NOTIFICATION_LONG_PRESS_NAME) boolean allowNotificationLongPress,
+            NotifPipelineInitializer notifPipelineInitializer,
+            FalsingManager falsingManager,
+            BroadcastDispatcher broadcastDispatcher,
+            RemoteInputQuickSettingsDisabler remoteInputQuickSettingsDisabler,
+            NotificationGutsManager notificationGutsManager,
+            NotificationLogger notificationLogger,
+            NotificationEntryManager notificationEntryManager,
+            NotificationInterruptionStateProvider notificationInterruptionStateProvider,
+            NotificationViewHierarchyManager notificationViewHierarchyManager,
+            ForegroundServiceController foregroundServiceController,
+            AppOpsController appOpsController,
+            KeyguardViewMediator keyguardViewMediator,
+            ZenModeController zenModeController,
+            NotificationAlertingManager notificationAlertingManager,
+            DisplayMetrics displayMetrics,
+            MetricsLogger metricsLogger,
+            UiOffloadThread uiOffloadThread,
+            NotificationMediaManager notificationMediaManager,
+            NotificationLockscreenUserManager lockScreenUserManager,
+            NotificationRemoteInputManager remoteInputManager,
+            UserSwitcherController userSwitcherController,
+            NetworkController networkController,
+            BatteryController batteryController,
+            SysuiColorExtractor colorExtractor,
+            ScreenLifecycle screenLifecycle,
+            WakefulnessLifecycle wakefulnessLifecycle,
+            SysuiStatusBarStateController statusBarStateController,
+            VibratorHelper vibratorHelper,
+            BubbleController bubbleController,
+            NotificationGroupManager groupManager,
+            NotificationGroupAlertTransferHelper groupAlertTransferHelper,
+            VisualStabilityManager visualStabilityManager,
+            DeviceProvisionedController deviceProvisionedController,
+            NavigationBarController navigationBarController,
+            AssistManager assistManager,
+            NotificationListener notificationListener,
+            ConfigurationController configurationController,
+            StatusBarWindowController statusBarWindowController,
+            StatusBarWindowViewController.Builder statusBarWindowViewControllerBuild,
+            NotifLog notifLog) {
+        super(
+                context,
+                lightBarController,
+                autoHideController,
+                keyguardUpdateMonitor,
+                statusBarIconController,
+                dozeLog,
+                injectionInflationController,
+                pulseExpansionHandler,
+                notificationWakeUpCoordinator,
+                keyguardBypassController,
+                keyguardStateController,
+                headsUpManagerPhone,
+                dynamicPrivacyController,
+                bypassHeadsUpNotifier,
+                allowNotificationLongPress,
+                notifPipelineInitializer,
+                falsingManager,
+                broadcastDispatcher,
+                remoteInputQuickSettingsDisabler,
+                notificationGutsManager,
+                notificationLogger,
+                notificationEntryManager,
+                notificationInterruptionStateProvider,
+                notificationViewHierarchyManager,
+                foregroundServiceController,
+                appOpsController,
+                keyguardViewMediator,
+                zenModeController,
+                notificationAlertingManager,
+                displayMetrics,
+                metricsLogger,
+                uiOffloadThread,
+                notificationMediaManager,
+                lockScreenUserManager,
+                remoteInputManager,
+                userSwitcherController,
+                networkController,
+                batteryController,
+                colorExtractor,
+                screenLifecycle,
+                wakefulnessLifecycle,
+                statusBarStateController,
+                vibratorHelper,
+                bubbleController,
+                groupManager,
+                groupAlertTransferHelper,
+                visualStabilityManager,
+                deviceProvisionedController,
+                navigationBarController,
+                assistManager,
+                notificationListener,
+                configurationController,
+                statusBarWindowController,
+                statusBarWindowViewControllerBuild,
+                notifLog);
+        mNavigationBarController = navigationBarController;
+    }
+
     @Override
     public void start() {
         // get the provisioned state before calling the parent class since it's that flow that
@@ -616,7 +786,7 @@
             return;
         }
         mStatusBarWindowController.setStatusBarFocusable(false);
-        mStatusBarWindow.cancelExpandHelper();
+        mStatusBarWindowViewController.cancelExpandHelper();
         mStatusBarView.collapsePanel(true /* animate */, delayed, speedUpFactor);
 
         animateNotificationPanel(mClosingVelocity, true);
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 827a59e..886162f 100644
--- a/packages/CarSystemUI/src/com/android/systemui/statusbar/car/UserGridRecyclerView.java
+++ b/packages/CarSystemUI/src/com/android/systemui/statusbar/car/UserGridRecyclerView.java
@@ -23,13 +23,17 @@
 import android.app.AlertDialog.Builder;
 import android.app.Dialog;
 import android.car.userlib.CarUserManagerHelper;
+import android.content.BroadcastReceiver;
 import android.content.Context;
 import android.content.DialogInterface;
+import android.content.Intent;
+import android.content.IntentFilter;
 import android.content.pm.UserInfo;
 import android.content.res.Resources;
 import android.graphics.Bitmap;
 import android.graphics.Rect;
 import android.os.AsyncTask;
+import android.os.UserHandle;
 import android.util.AttributeSet;
 import android.view.LayoutInflater;
 import android.view.View;
@@ -53,13 +57,19 @@
  * Displays a GridLayout with icons for the users in the system to allow switching between users.
  * One of the uses of this is for the lock screen in auto.
  */
-public class UserGridRecyclerView extends RecyclerView implements
-        CarUserManagerHelper.OnUsersUpdateListener {
+public class UserGridRecyclerView extends RecyclerView {
     private UserSelectionListener mUserSelectionListener;
     private UserAdapter mAdapter;
     private CarUserManagerHelper mCarUserManagerHelper;
     private Context mContext;
 
+    private final BroadcastReceiver mUserUpdateReceiver = new BroadcastReceiver() {
+        @Override
+        public void onReceive(Context context, Intent intent) {
+            onUsersUpdate();
+        }
+    };
+
     public UserGridRecyclerView(Context context, AttributeSet attrs) {
         super(context, attrs);
         mContext = context;
@@ -75,7 +85,7 @@
     @Override
     public void onFinishInflate() {
         super.onFinishInflate();
-        mCarUserManagerHelper.registerOnUsersUpdateListener(this);
+        registerForUserEvents();
     }
 
     /**
@@ -84,7 +94,7 @@
     @Override
     public void onDetachedFromWindow() {
         super.onDetachedFromWindow();
-        mCarUserManagerHelper.unregisterOnUsersUpdateListener(this);
+        unregisterForUserEvents();
     }
 
     /**
@@ -161,13 +171,30 @@
         mUserSelectionListener = userSelectionListener;
     }
 
-    @Override
-    public void onUsersUpdate() {
+    private void onUsersUpdate() {
         mAdapter.clearUsers();
         mAdapter.updateUsers(createUserRecords(mCarUserManagerHelper.getAllUsers()));
         mAdapter.notifyDataSetChanged();
     }
 
+    private void registerForUserEvents() {
+        IntentFilter filter = new IntentFilter();
+        filter.addAction(Intent.ACTION_USER_REMOVED);
+        filter.addAction(Intent.ACTION_USER_ADDED);
+        filter.addAction(Intent.ACTION_USER_INFO_CHANGED);
+        filter.addAction(Intent.ACTION_USER_SWITCHED);
+        mContext.registerReceiverAsUser(
+                mUserUpdateReceiver,
+                UserHandle.ALL, // Necessary because CarSystemUi lives in User 0
+                filter,
+                /* broadcastPermission= */ null,
+                /* scheduler= */ null);
+    }
+
+    private void unregisterForUserEvents() {
+        mContext.unregisterReceiver(mUserUpdateReceiver);
+    }
+
     /**
      * Adapter to populate the grid layout with the available user profiles
      */
diff --git a/packages/CarSystemUI/src/com/android/systemui/volume/CarVolumeDialogComponent.java b/packages/CarSystemUI/src/com/android/systemui/volume/CarVolumeDialogComponent.java
index 71cc19b..4d6af95 100644
--- a/packages/CarSystemUI/src/com/android/systemui/volume/CarVolumeDialogComponent.java
+++ b/packages/CarSystemUI/src/com/android/systemui/volume/CarVolumeDialogComponent.java
@@ -19,15 +19,21 @@
 import android.content.Context;
 
 import com.android.systemui.SystemUI;
+import com.android.systemui.keyguard.KeyguardViewMediator;
 import com.android.systemui.plugins.VolumeDialog;
 
+import javax.inject.Inject;
+import javax.inject.Singleton;
+
 /**
  * Allows for adding car specific dialog when the volume dialog is created.
  */
+@Singleton
 public class CarVolumeDialogComponent extends VolumeDialogComponent {
 
-    public CarVolumeDialogComponent(SystemUI sysui, Context context) {
-        super(sysui, context);
+    @Inject
+    public CarVolumeDialogComponent(Context context, KeyguardViewMediator keyguardViewMediator) {
+        super(context, keyguardViewMediator);
     }
 
     protected VolumeDialog createDefault() {
diff --git a/packages/SettingsLib/Tile/src/com/android/settingslib/drawer/ActivityTile.java b/packages/SettingsLib/Tile/src/com/android/settingslib/drawer/ActivityTile.java
new file mode 100644
index 0000000..06a4a45
--- /dev/null
+++ b/packages/SettingsLib/Tile/src/com/android/settingslib/drawer/ActivityTile.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.settingslib.drawer;
+
+import android.content.Context;
+import android.content.Intent;
+import android.content.pm.ComponentInfo;
+import android.content.pm.PackageManager;
+import android.content.pm.ResolveInfo;
+import android.os.Parcel;
+import android.util.Log;
+
+import java.util.List;
+import java.util.Objects;
+
+/**
+ * Description of a single dashboard tile which is generated from an activity.
+ */
+public class ActivityTile extends Tile {
+    private static final String TAG = "ActivityTile";
+
+    public ActivityTile(ComponentInfo info, String category) {
+        super(info, category);
+        setMetaData(info.metaData);
+    }
+
+    ActivityTile(Parcel in) {
+        super(in);
+    }
+
+    @Override
+    public int getId() {
+        return Objects.hash(getPackageName(), getComponentName());
+    }
+
+    @Override
+    public String getDescription() {
+        return getPackageName() + "/" + getComponentName();
+    }
+
+    @Override
+    protected CharSequence getComponentLabel(Context context) {
+        final PackageManager pm = context.getPackageManager();
+        final ComponentInfo info = getComponentInfo(context);
+        return info == null
+                ? null
+                : info.loadLabel(pm);
+    }
+
+    @Override
+    protected ComponentInfo getComponentInfo(Context context) {
+        if (mComponentInfo == null) {
+            final PackageManager pm = context.getApplicationContext().getPackageManager();
+            final Intent intent = getIntent();
+            final List<ResolveInfo> infoList =
+                    pm.queryIntentActivities(intent, PackageManager.GET_META_DATA);
+            if (infoList != null && !infoList.isEmpty()) {
+                mComponentInfo = infoList.get(0).activityInfo;
+                setMetaData(mComponentInfo.metaData);
+            } else {
+                Log.e(TAG, "Cannot find package info for "
+                        + intent.getComponent().flattenToString());
+            }
+        }
+        return mComponentInfo;
+    }
+}
diff --git a/packages/SettingsLib/Tile/src/com/android/settingslib/drawer/Tile.java b/packages/SettingsLib/Tile/src/com/android/settingslib/drawer/Tile.java
index ca2d1ed..722f734 100644
--- a/packages/SettingsLib/Tile/src/com/android/settingslib/drawer/Tile.java
+++ b/packages/SettingsLib/Tile/src/com/android/settingslib/drawer/Tile.java
@@ -30,9 +30,8 @@
 
 import android.content.Context;
 import android.content.Intent;
-import android.content.pm.ActivityInfo;
+import android.content.pm.ComponentInfo;
 import android.content.pm.PackageManager;
-import android.content.pm.ResolveInfo;
 import android.content.res.Resources;
 import android.content.res.TypedArray;
 import android.graphics.drawable.Icon;
@@ -47,13 +46,11 @@
 
 import java.util.ArrayList;
 import java.util.Comparator;
-import java.util.List;
-import java.util.Objects;
 
 /**
  * Description of a single dashboard tile that the user can select.
  */
-public class Tile implements Parcelable {
+public abstract class Tile implements Parcelable {
 
     private static final String TAG = "Tile";
 
@@ -64,28 +61,27 @@
 
     @VisibleForTesting
     long mLastUpdateTime;
-    private final String mActivityPackage;
-    private final String mActivityName;
+    private final String mComponentPackage;
+    private final String mComponentName;
     private final Intent mIntent;
 
-    private ActivityInfo mActivityInfo;
+    protected ComponentInfo mComponentInfo;
     private CharSequence mSummaryOverride;
     private Bundle mMetaData;
     private String mCategory;
 
-    public Tile(ActivityInfo activityInfo, String category) {
-        mActivityInfo = activityInfo;
-        mActivityPackage = mActivityInfo.packageName;
-        mActivityName = mActivityInfo.name;
-        mMetaData = activityInfo.metaData;
+    public Tile(ComponentInfo info, String category) {
+        mComponentInfo = info;
+        mComponentPackage = mComponentInfo.packageName;
+        mComponentName = mComponentInfo.name;
         mCategory = category;
-        mIntent = new Intent().setClassName(mActivityPackage, mActivityName);
+        mIntent = new Intent().setClassName(mComponentPackage, mComponentName);
     }
 
     Tile(Parcel in) {
-        mActivityPackage = in.readString();
-        mActivityName = in.readString();
-        mIntent = new Intent().setClassName(mActivityPackage, mActivityName);
+        mComponentPackage = in.readString();
+        mComponentName = in.readString();
+        mIntent = new Intent().setClassName(mComponentPackage, mComponentName);
         final int number = in.readInt();
         for (int i = 0; i < number; i++) {
             userHandle.add(UserHandle.CREATOR.createFromParcel(in));
@@ -101,8 +97,8 @@
 
     @Override
     public void writeToParcel(Parcel dest, int flags) {
-        dest.writeString(mActivityPackage);
-        dest.writeString(mActivityName);
+        dest.writeString(mComponentPackage);
+        dest.writeString(mComponentName);
         final int size = userHandle.size();
         dest.writeInt(size);
         for (int i = 0; i < size; i++) {
@@ -112,16 +108,22 @@
         dest.writeBundle(mMetaData);
     }
 
-    public int getId() {
-        return Objects.hash(mActivityPackage, mActivityName);
-    }
+    /**
+     * Unique ID of the tile
+     */
+    public abstract int getId();
 
-    public String getDescription() {
-        return mActivityPackage + "/" + mActivityName;
-    }
+    /**
+     * Human-readable description of the tile
+     */
+    public abstract String getDescription();
 
     public String getPackageName() {
-        return mActivityPackage;
+        return mComponentPackage;
+    }
+
+    public String getComponentName() {
+        return mComponentName;
     }
 
     /**
@@ -154,7 +156,7 @@
     }
 
     /**
-     * Check whether title has order.
+     * Check whether tile has order.
      */
     public boolean hasOrder() {
         return mMetaData.containsKey(META_DATA_KEY_ORDER)
@@ -170,14 +172,14 @@
         final PackageManager packageManager = context.getPackageManager();
         if (mMetaData.containsKey(META_DATA_PREFERENCE_TITLE)) {
             if (mMetaData.containsKey(META_DATA_PREFERENCE_TITLE_URI)) {
-                // If has as uri to provide dynamic summary, skip loading here. UI will later load
+                // If has as uri to provide dynamic title, skip loading here. UI will later load
                 // at tile binding time.
                 return null;
             }
             if (mMetaData.get(META_DATA_PREFERENCE_TITLE) instanceof Integer) {
                 try {
                     final Resources res =
-                            packageManager.getResourcesForApplication(mActivityPackage);
+                            packageManager.getResourcesForApplication(mComponentPackage);
                     title = res.getString(mMetaData.getInt(META_DATA_PREFERENCE_TITLE));
                 } catch (PackageManager.NameNotFoundException | Resources.NotFoundException e) {
                     Log.w(TAG, "Couldn't find info", e);
@@ -186,18 +188,15 @@
                 title = mMetaData.getString(META_DATA_PREFERENCE_TITLE);
             }
         }
-        // Set the preference title to the activity's label if no
-        // meta-data is found
+        // Set the preference title by the component if no meta-data is found
         if (title == null) {
-            final ActivityInfo activityInfo = getActivityInfo(context);
-            if (activityInfo == null) {
-                return null;
-            }
-            title = activityInfo.loadLabel(packageManager);
+            title = getComponentLabel(context);
         }
         return title;
     }
 
+    protected abstract CharSequence getComponentLabel(Context context);
+
     /**
      * Overrides the summary. This can happen when injected tile wants to provide dynamic summary.
      */
@@ -225,7 +224,7 @@
                 if (mMetaData.get(META_DATA_PREFERENCE_SUMMARY) instanceof Integer) {
                     try {
                         final Resources res =
-                                packageManager.getResourcesForApplication(mActivityPackage);
+                                packageManager.getResourcesForApplication(mComponentPackage);
                         summary = res.getString(mMetaData.getInt(META_DATA_PREFERENCE_SUMMARY));
                     } catch (PackageManager.NameNotFoundException | Resources.NotFoundException e) {
                         Log.d(TAG, "Couldn't find info", e);
@@ -281,24 +280,24 @@
             return null;
         }
         ensureMetadataNotStale(context);
-        final ActivityInfo activityInfo = getActivityInfo(context);
-        if (activityInfo == null) {
-            Log.w(TAG, "Cannot find ActivityInfo for " + getDescription());
+        final ComponentInfo componentInfo = getComponentInfo(context);
+        if (componentInfo == null) {
+            Log.w(TAG, "Cannot find ComponentInfo for " + getDescription());
             return null;
         }
 
         int iconResId = mMetaData.getInt(META_DATA_PREFERENCE_ICON);
         // Set the icon
         if (iconResId == 0) {
-            // Only fallback to activityinfo.icon if metadata does not contain ICON_URI.
+            // Only fallback to componentInfo.icon if metadata does not contain ICON_URI.
             // ICON_URI should be loaded in app UI when need the icon object. Handling IPC at this
             // level is too complex because we don't have a strong threading contract for this class
             if (!mMetaData.containsKey(META_DATA_PREFERENCE_ICON_URI)) {
-                iconResId = activityInfo.icon;
+                iconResId = componentInfo.icon;
             }
         }
         if (iconResId != 0) {
-            final Icon icon = Icon.createWithResource(activityInfo.packageName, iconResId);
+            final Icon icon = Icon.createWithResource(componentInfo.packageName, iconResId);
             if (isIconTintable(context)) {
                 final TypedArray a = context.obtainStyledAttributes(new int[]{
                         android.R.attr.colorControlNormal});
@@ -331,41 +330,26 @@
         final PackageManager pm = context.getApplicationContext().getPackageManager();
 
         try {
-            final long lastUpdateTime = pm.getPackageInfo(mActivityPackage,
+            final long lastUpdateTime = pm.getPackageInfo(mComponentPackage,
                     PackageManager.GET_META_DATA).lastUpdateTime;
             if (lastUpdateTime == mLastUpdateTime) {
                 // All good. Do nothing
                 return;
             }
             // App has been updated since we load metadata last time. Reload metadata.
-            mActivityInfo = null;
-            getActivityInfo(context);
+            mComponentInfo = null;
+            getComponentInfo(context);
             mLastUpdateTime = lastUpdateTime;
         } catch (PackageManager.NameNotFoundException e) {
             Log.d(TAG, "Can't find package, probably uninstalled.");
         }
     }
 
-    private ActivityInfo getActivityInfo(Context context) {
-        if (mActivityInfo == null) {
-            final PackageManager pm = context.getApplicationContext().getPackageManager();
-            final Intent intent = new Intent().setClassName(mActivityPackage, mActivityName);
-            final List<ResolveInfo> infoList =
-                    pm.queryIntentActivities(intent, PackageManager.GET_META_DATA);
-            if (infoList != null && !infoList.isEmpty()) {
-                mActivityInfo = infoList.get(0).activityInfo;
-                mMetaData = mActivityInfo.metaData;
-            } else {
-                Log.e(TAG, "Cannot find package info for "
-                        + intent.getComponent().flattenToString());
-            }
-        }
-        return mActivityInfo;
-    }
+    protected abstract ComponentInfo getComponentInfo(Context context);
 
     public static final Creator<Tile> CREATOR = new Creator<Tile>() {
         public Tile createFromParcel(Parcel source) {
-            return new Tile(source);
+            return new ActivityTile(source);
         }
 
         public Tile[] newArray(int size) {
diff --git a/packages/SettingsLib/Tile/src/com/android/settingslib/drawer/TileUtils.java b/packages/SettingsLib/Tile/src/com/android/settingslib/drawer/TileUtils.java
index aced5ef..c4df2e8 100644
--- a/packages/SettingsLib/Tile/src/com/android/settingslib/drawer/TileUtils.java
+++ b/packages/SettingsLib/Tile/src/com/android/settingslib/drawer/TileUtils.java
@@ -20,6 +20,7 @@
 import android.content.IContentProvider;
 import android.content.Intent;
 import android.content.pm.ActivityInfo;
+import android.content.pm.ComponentInfo;
 import android.content.pm.PackageManager;
 import android.content.pm.ResolveInfo;
 import android.net.Uri;
@@ -127,6 +128,7 @@
      */
     public static final String META_DATA_PREFERENCE_ICON_BACKGROUND_HINT =
             "com.android.settings.bg.hint";
+
     /**
      * Name of the meta-data item that should be set in the AndroidManifest.xml
      * to specify the icon background color as raw ARGB.
@@ -220,10 +222,11 @@
     public static List<DashboardCategory> getCategories(Context context,
             Map<Pair<String, String>, Tile> cache) {
         final long startTime = System.currentTimeMillis();
-        boolean setup = Global.getInt(context.getContentResolver(), Global.DEVICE_PROVISIONED, 0)
-                != 0;
-        ArrayList<Tile> tiles = new ArrayList<>();
-        UserManager userManager = (UserManager) context.getSystemService(Context.USER_SERVICE);
+        final boolean setup =
+                Global.getInt(context.getContentResolver(), Global.DEVICE_PROVISIONED, 0) != 0;
+        final ArrayList<Tile> tiles = new ArrayList<>();
+        final UserManager userManager = (UserManager) context.getSystemService(
+                Context.USER_SERVICE);
         for (UserHandle user : userManager.getUserProfiles()) {
             // TODO: Needs much optimization, too many PM queries going on here.
             if (user.getIdentifier() == ActivityManager.getCurrentUser()) {
@@ -240,7 +243,7 @@
             }
         }
 
-        HashMap<String, DashboardCategory> categoryMap = new HashMap<>();
+        final HashMap<String, DashboardCategory> categoryMap = new HashMap<>();
         for (Tile tile : tiles) {
             final String categoryKey = tile.getCategory();
             DashboardCategory category = categoryMap.get(categoryKey);
@@ -255,7 +258,7 @@
             }
             category.addTile(tile);
         }
-        ArrayList<DashboardCategory> categories = new ArrayList<>(categoryMap.values());
+        final ArrayList<DashboardCategory> categories = new ArrayList<>(categoryMap.values());
         for (DashboardCategory category : categories) {
             category.sortTiles();
         }
@@ -275,63 +278,90 @@
         if (requireSettings) {
             intent.setPackage(SETTING_PKG);
         }
+        getActivityTiles(context, user, addedCache, defaultCategory, outTiles, intent);
+    }
+
+    private static void getActivityTiles(Context context,
+            UserHandle user, Map<Pair<String, String>, Tile> addedCache,
+            String defaultCategory, List<Tile> outTiles, Intent intent) {
         final PackageManager pm = context.getPackageManager();
-        List<ResolveInfo> results = pm.queryIntentActivitiesAsUser(intent,
+        final List<ResolveInfo> results = pm.queryIntentActivitiesAsUser(intent,
                 PackageManager.GET_META_DATA, user.getIdentifier());
         for (ResolveInfo resolved : results) {
             if (!resolved.system) {
                 // Do not allow any app to add to settings, only system ones.
                 continue;
             }
-            ActivityInfo activityInfo = resolved.activityInfo;
-            Bundle metaData = activityInfo.metaData;
-            String categoryKey = defaultCategory;
-
-            // Load category
-            if ((metaData == null || !metaData.containsKey(EXTRA_CATEGORY_KEY))
-                    && categoryKey == null) {
-                Log.w(LOG_TAG, "Found " + resolved.activityInfo.name + " for intent "
-                        + intent + " missing metadata "
-                        + (metaData == null ? "" : EXTRA_CATEGORY_KEY));
-                continue;
-            } else {
-                categoryKey = metaData.getString(EXTRA_CATEGORY_KEY);
-            }
-
-            Pair<String, String> key = new Pair<>(activityInfo.packageName, activityInfo.name);
-            Tile tile = addedCache.get(key);
-            if (tile == null) {
-                tile = new Tile(activityInfo, categoryKey);
-                addedCache.put(key, tile);
-            } else {
-                tile.setMetaData(metaData);
-            }
-
-            if (!tile.userHandle.contains(user)) {
-                tile.userHandle.add(user);
-            }
-            if (!outTiles.contains(tile)) {
-                outTiles.add(tile);
-            }
+            final ActivityInfo activityInfo = resolved.activityInfo;
+            final Bundle metaData = activityInfo.metaData;
+            getTile(user, addedCache, defaultCategory, outTiles, intent, metaData, activityInfo);
         }
     }
 
+    private static void getTile(UserHandle user, Map<Pair<String, String>, Tile> addedCache,
+            String defaultCategory, List<Tile> outTiles, Intent intent, Bundle metaData,
+            ComponentInfo componentInfo) {
+        String categoryKey = defaultCategory;
+        // Load category
+        if ((metaData == null || !metaData.containsKey(EXTRA_CATEGORY_KEY))
+                && categoryKey == null) {
+            Log.w(LOG_TAG, "Found " + componentInfo.name + " for intent "
+                    + intent + " missing metadata "
+                    + (metaData == null ? "" : EXTRA_CATEGORY_KEY));
+            return;
+        } else {
+            categoryKey = metaData.getString(EXTRA_CATEGORY_KEY);
+        }
+
+        final Pair<String, String> key = new Pair<>(componentInfo.packageName, componentInfo.name);
+        Tile tile = addedCache.get(key);
+        if (tile == null) {
+            tile = new ActivityTile(componentInfo, categoryKey);
+            addedCache.put(key, tile);
+        } else {
+            tile.setMetaData(metaData);
+        }
+
+        if (!tile.userHandle.contains(user)) {
+            tile.userHandle.add(user);
+        }
+        if (!outTiles.contains(tile)) {
+            outTiles.add(tile);
+        }
+    }
+
+    /**
+     * Returns the complete uri from the meta data key of the tile.
+
+     * @param tile          Tile which contains meta data
+     * @param metaDataKey   Key mapping to the uri in meta data
+     * @return Uri associated with the key
+     */
+    public static Uri getCompleteUri(Tile tile, String metaDataKey) {
+        final String uriString = tile.getMetaData().getString(metaDataKey);
+        if (TextUtils.isEmpty(uriString)) {
+            return null;
+        }
+
+        return Uri.parse(uriString);
+    }
+
     /**
      * Gets the icon package name and resource id from content provider.
      *
      * @param context     context
      * @param packageName package name of the target activity
-     * @param uriString   URI for the content provider
+     * @param uri         URI for the content provider
      * @param providerMap Maps URI authorities to providers
      * @return package name and resource id of the icon specified
      */
     public static Pair<String, Integer> getIconFromUri(Context context, String packageName,
-            String uriString, Map<String, IContentProvider> providerMap) {
-        Bundle bundle = getBundleFromUri(context, uriString, providerMap);
+            Uri uri, Map<String, IContentProvider> providerMap) {
+        final Bundle bundle = getBundleFromUri(context, uri, providerMap, null);
         if (bundle == null) {
             return null;
         }
-        String iconPackageName = bundle.getString(EXTRA_PREFERENCE_ICON_PACKAGE);
+        final String iconPackageName = bundle.getString(EXTRA_PREFERENCE_ICON_PACKAGE);
         if (TextUtils.isEmpty(iconPackageName)) {
             return null;
         }
@@ -342,7 +372,7 @@
         // Icon can either come from the target package or from the Settings app.
         if (iconPackageName.equals(packageName)
                 || iconPackageName.equals(context.getPackageName())) {
-            return Pair.create(iconPackageName, bundle.getInt(META_DATA_PREFERENCE_ICON, 0));
+            return Pair.create(iconPackageName, resId);
         }
         return null;
     }
@@ -351,34 +381,33 @@
      * Gets text associated with the input key from the content provider.
      *
      * @param context     context
-     * @param uriString   URI for the content provider
+     * @param uri         URI for the content provider
      * @param providerMap Maps URI authorities to providers
      * @param key         Key mapping to the text in bundle returned by the content provider
      * @return Text associated with the key, if returned by the content provider
      */
-    public static String getTextFromUri(Context context, String uriString,
+    public static String getTextFromUri(Context context, Uri uri,
             Map<String, IContentProvider> providerMap, String key) {
-        Bundle bundle = getBundleFromUri(context, uriString, providerMap);
+        final Bundle bundle = getBundleFromUri(context, uri, providerMap, null);
         return (bundle != null) ? bundle.getString(key) : null;
     }
 
-    private static Bundle getBundleFromUri(Context context, String uriString,
-            Map<String, IContentProvider> providerMap) {
-        if (TextUtils.isEmpty(uriString)) {
+    private static Bundle getBundleFromUri(Context context, Uri uri,
+            Map<String, IContentProvider> providerMap, Bundle bundle) {
+        if (uri == null) {
             return null;
         }
-        Uri uri = Uri.parse(uriString);
-        String method = getMethodFromUri(uri);
+        final String method = getMethodFromUri(uri);
         if (TextUtils.isEmpty(method)) {
             return null;
         }
-        IContentProvider provider = getProviderFromUri(context, uri, providerMap);
+        final IContentProvider provider = getProviderFromUri(context, uri, providerMap);
         if (provider == null) {
             return null;
         }
         try {
             return provider.call(context.getPackageName(), uri.getAuthority(),
-                    method, uriString, null);
+                    method, uri.toString(), bundle);
         } catch (RemoteException e) {
             return null;
         }
@@ -389,7 +418,7 @@
         if (uri == null) {
             return null;
         }
-        String authority = uri.getAuthority();
+        final String authority = uri.getAuthority();
         if (TextUtils.isEmpty(authority)) {
             return null;
         }
@@ -400,7 +429,7 @@
     }
 
     /** Returns the first path segment of the uri if it exists as the method, otherwise null. */
-    static String getMethodFromUri(Uri uri) {
+    private static String getMethodFromUri(Uri uri) {
         if (uri == null) {
             return null;
         }
diff --git a/packages/SettingsLib/res/values-af/strings.xml b/packages/SettingsLib/res/values-af/strings.xml
index 4cedc93..245ca14 100644
--- a/packages/SettingsLib/res/values-af/strings.xml
+++ b/packages/SettingsLib/res/values-af/strings.xml
@@ -402,8 +402,8 @@
     <string name="power_remaining_duration_shutdown_imminent" product="tablet" msgid="7466484148515796216">"Tablet kan binnekort afgaan (<xliff:g id="LEVEL">%1$s</xliff:g>)"</string>
     <string name="power_remaining_duration_shutdown_imminent" product="device" msgid="603933521600231649">"Toestel kan binnekort afgaan (<xliff:g id="LEVEL">%1$s</xliff:g>)"</string>
     <string name="power_charging" msgid="1779532561355864267">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="STATE">%2$s</xliff:g>"</string>
-    <string name="power_remaining_charging_duration_only" msgid="1421102457410268886">"<xliff:g id="TIME">%1$s</xliff:g> oor tot vol gelaai"</string>
-    <string name="power_charging_duration" msgid="4676999980973411875">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g> tot vol gelaai"</string>
+    <string name="power_remaining_charging_duration_only" msgid="6672239353042034265">"<xliff:g id="TIME">%1$s</xliff:g> oor tot battery gelaai is"</string>
+    <string name="power_charging_duration" msgid="5850751284103249125">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g> tot battery gelaai is"</string>
     <string name="battery_info_status_unknown" msgid="196130600938058547">"Onbekend"</string>
     <string name="battery_info_status_charging" msgid="1705179948350365604">"Laai"</string>
     <string name="battery_info_status_charging_lower" msgid="8689770213898117994">"laai tans"</string>
diff --git a/packages/SettingsLib/res/values-am/strings.xml b/packages/SettingsLib/res/values-am/strings.xml
index 3b7abdb..bfd3196 100644
--- a/packages/SettingsLib/res/values-am/strings.xml
+++ b/packages/SettingsLib/res/values-am/strings.xml
@@ -402,8 +402,8 @@
     <string name="power_remaining_duration_shutdown_imminent" product="tablet" msgid="7466484148515796216">"ጡባዊው በቅርቡ ሊዘጋ ይችላል (<xliff:g id="LEVEL">%1$s</xliff:g>)"</string>
     <string name="power_remaining_duration_shutdown_imminent" product="device" msgid="603933521600231649">"መሣሪያው በቅርቡ ሊዘጋ ይችላል (<xliff:g id="LEVEL">%1$s</xliff:g>)"</string>
     <string name="power_charging" msgid="1779532561355864267">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string>
-    <string name="power_remaining_charging_duration_only" msgid="1421102457410268886">"ሙሉ ኃይል እስኪሞላ ድረስ <xliff:g id="TIME">%1$s</xliff:g>"</string>
-    <string name="power_charging_duration" msgid="4676999980973411875">"<xliff:g id="LEVEL">%1$s</xliff:g> - ሙሉ ለሙሉ እስኪሞላ ድረስ <xliff:g id="TIME">%2$s</xliff:g>"</string>
+    <string name="power_remaining_charging_duration_only" msgid="6672239353042034265">"<xliff:g id="TIME">%1$s</xliff:g> ኃይል እስከሚሞላ ድረስ ይቀራል"</string>
+    <string name="power_charging_duration" msgid="5850751284103249125">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> ኃይል እስከሚሞላ ድረስ"</string>
     <string name="battery_info_status_unknown" msgid="196130600938058547">"ያልታወቀ"</string>
     <string name="battery_info_status_charging" msgid="1705179948350365604">"ኃይል በመሙላት ላይ"</string>
     <string name="battery_info_status_charging_lower" msgid="8689770213898117994">"ኃይል በመሙላት ላይ"</string>
diff --git a/packages/SettingsLib/res/values-ar/strings.xml b/packages/SettingsLib/res/values-ar/strings.xml
index df1ec30..8b67b0b 100644
--- a/packages/SettingsLib/res/values-ar/strings.xml
+++ b/packages/SettingsLib/res/values-ar/strings.xml
@@ -402,8 +402,8 @@
     <string name="power_remaining_duration_shutdown_imminent" product="tablet" msgid="7466484148515796216">"قد يتم إغلاق الجهاز اللوحي بعد قليل (<xliff:g id="LEVEL">%1$s</xliff:g>)."</string>
     <string name="power_remaining_duration_shutdown_imminent" product="device" msgid="603933521600231649">"قد يتم إغلاق الجهاز بعد قليل (<xliff:g id="LEVEL">%1$s</xliff:g>)."</string>
     <string name="power_charging" msgid="1779532561355864267">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string>
-    <string name="power_remaining_charging_duration_only" msgid="1421102457410268886">"يتبقى <xliff:g id="TIME">%1$s</xliff:g> لشحن البطارية بالكامل"</string>
-    <string name="power_charging_duration" msgid="4676999980973411875">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> حتى يكتمل الشحن"</string>
+    <string name="power_remaining_charging_duration_only" msgid="6672239353042034265">"<xliff:g id="TIME">%1$s</xliff:g> إلى أن يتم شحن الجهاز بالكامل"</string>
+    <string name="power_charging_duration" msgid="5850751284103249125">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> إلى أن يتم شحن الجهاز بالكامل"</string>
     <string name="battery_info_status_unknown" msgid="196130600938058547">"غير معروف"</string>
     <string name="battery_info_status_charging" msgid="1705179948350365604">"جارٍ الشحن"</string>
     <string name="battery_info_status_charging_lower" msgid="8689770213898117994">"جارٍ الشحن"</string>
diff --git a/packages/SettingsLib/res/values-as/strings.xml b/packages/SettingsLib/res/values-as/strings.xml
index 9c25b66..f3ca337 100644
--- a/packages/SettingsLib/res/values-as/strings.xml
+++ b/packages/SettingsLib/res/values-as/strings.xml
@@ -402,8 +402,8 @@
     <string name="power_remaining_duration_shutdown_imminent" product="tablet" msgid="7466484148515796216">"টেবলেটটো সোনকালেই বন্ধ হ\'ব পাৰে (<xliff:g id="LEVEL">%1$s</xliff:g>)"</string>
     <string name="power_remaining_duration_shutdown_imminent" product="device" msgid="603933521600231649">"ডিভাইচটো সোনকালেই বন্ধ হ\'ব পাৰে (<xliff:g id="LEVEL">%1$s</xliff:g>)"</string>
     <string name="power_charging" msgid="1779532561355864267">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string>
-    <string name="power_remaining_charging_duration_only" msgid="1421102457410268886">"সম্পূৰ্ণকৈ চ্চাৰ্জ হ\'বলৈ <xliff:g id="TIME">%1$s</xliff:g> বাকী"</string>
-    <string name="power_charging_duration" msgid="4676999980973411875">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> সম্পূৰ্ণৰূপে চ্চাৰ্জ হোৱা পৰ্যন্ত"</string>
+    <string name="power_remaining_charging_duration_only" msgid="6672239353042034265">"চাৰ্জ হ’বলৈ <xliff:g id="TIME">%1$s</xliff:g> বাকী আছে"</string>
+    <string name="power_charging_duration" msgid="5850751284103249125">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> চাৰ্জ হ\'বলৈ"</string>
     <string name="battery_info_status_unknown" msgid="196130600938058547">"অজ্ঞাত"</string>
     <string name="battery_info_status_charging" msgid="1705179948350365604">"চাৰ্জ কৰি থকা হৈছে"</string>
     <string name="battery_info_status_charging_lower" msgid="8689770213898117994">"চ্চাৰ্জ হৈ আছে"</string>
diff --git a/packages/SettingsLib/res/values-az/strings.xml b/packages/SettingsLib/res/values-az/strings.xml
index 3a6d301..d35dfe8 100644
--- a/packages/SettingsLib/res/values-az/strings.xml
+++ b/packages/SettingsLib/res/values-az/strings.xml
@@ -402,8 +402,8 @@
     <string name="power_remaining_duration_shutdown_imminent" product="tablet" msgid="7466484148515796216">"Planşet tezliklə sönə bilər (<xliff:g id="LEVEL">%1$s</xliff:g>)"</string>
     <string name="power_remaining_duration_shutdown_imminent" product="device" msgid="603933521600231649">"Cihaz tezliklə sönə bilər (<xliff:g id="LEVEL">%1$s</xliff:g>)"</string>
     <string name="power_charging" msgid="1779532561355864267">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string>
-    <string name="power_remaining_charging_duration_only" msgid="1421102457410268886">"Tam enerji yığmağına <xliff:g id="TIME">%1$s</xliff:g> qalıb"</string>
-    <string name="power_charging_duration" msgid="4676999980973411875">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> tam enerji yığana kimi"</string>
+    <string name="power_remaining_charging_duration_only" msgid="6672239353042034265">"Enerjinin dolmasına <xliff:g id="TIME">%1$s</xliff:g> qalıb"</string>
+    <string name="power_charging_duration" msgid="5850751284103249125">"<xliff:g id="LEVEL">%1$s</xliff:g> - Enerjinin dolmasına <xliff:g id="TIME">%2$s</xliff:g> qalıb"</string>
     <string name="battery_info_status_unknown" msgid="196130600938058547">"Naməlum"</string>
     <string name="battery_info_status_charging" msgid="1705179948350365604">"Enerji doldurma"</string>
     <string name="battery_info_status_charging_lower" msgid="8689770213898117994">"enerji yığır"</string>
diff --git a/packages/SettingsLib/res/values-b+sr+Latn/strings.xml b/packages/SettingsLib/res/values-b+sr+Latn/strings.xml
index a8808fa..448de4b 100644
--- a/packages/SettingsLib/res/values-b+sr+Latn/strings.xml
+++ b/packages/SettingsLib/res/values-b+sr+Latn/strings.xml
@@ -402,8 +402,8 @@
     <string name="power_remaining_duration_shutdown_imminent" product="tablet" msgid="7466484148515796216">"Tablet će se uskoro isključiti (<xliff:g id="LEVEL">%1$s</xliff:g>)"</string>
     <string name="power_remaining_duration_shutdown_imminent" product="device" msgid="603933521600231649">"Uređaj će se uskoro isključiti (<xliff:g id="LEVEL">%1$s</xliff:g>)"</string>
     <string name="power_charging" msgid="1779532561355864267">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="STATE">%2$s</xliff:g>"</string>
-    <string name="power_remaining_charging_duration_only" msgid="1421102457410268886">"<xliff:g id="TIME">%1$s</xliff:g> do potpunog punjenja"</string>
-    <string name="power_charging_duration" msgid="4676999980973411875">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g> do potpunog punjenja"</string>
+    <string name="power_remaining_charging_duration_only" msgid="6672239353042034265">"Napuniće se za <xliff:g id="TIME">%1$s</xliff:g>"</string>
+    <string name="power_charging_duration" msgid="5850751284103249125">"<xliff:g id="LEVEL">%1$s</xliff:g> – napuniće se za <xliff:g id="TIME">%2$s</xliff:g>"</string>
     <string name="battery_info_status_unknown" msgid="196130600938058547">"Nepoznato"</string>
     <string name="battery_info_status_charging" msgid="1705179948350365604">"Puni se"</string>
     <string name="battery_info_status_charging_lower" msgid="8689770213898117994">"puni se"</string>
diff --git a/packages/SettingsLib/res/values-be/strings.xml b/packages/SettingsLib/res/values-be/strings.xml
index 05d9a5d..d68c0f3 100644
--- a/packages/SettingsLib/res/values-be/strings.xml
+++ b/packages/SettingsLib/res/values-be/strings.xml
@@ -402,8 +402,8 @@
     <string name="power_remaining_duration_shutdown_imminent" product="tablet" msgid="7466484148515796216">"Узровень зараду батарэі: <xliff:g id="LEVEL">%1$s</xliff:g>. Планшэт хутка спыніць працу."</string>
     <string name="power_remaining_duration_shutdown_imminent" product="device" msgid="603933521600231649">"Узровень зараду батарэі: <xliff:g id="LEVEL">%1$s</xliff:g>. Прылада хутка спыніць працу."</string>
     <string name="power_charging" msgid="1779532561355864267">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="STATE">%2$s</xliff:g>"</string>
-    <string name="power_remaining_charging_duration_only" msgid="1421102457410268886">"Да поўнай зарадкі засталося <xliff:g id="TIME">%1$s</xliff:g>"</string>
-    <string name="power_charging_duration" msgid="4676999980973411875">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g> да поўнай зарадкі"</string>
+    <string name="power_remaining_charging_duration_only" msgid="6672239353042034265">"Засталося <xliff:g id="TIME">%1$s</xliff:g> да поўнай зарадкі"</string>
+    <string name="power_charging_duration" msgid="5850751284103249125">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g> да поўнай зарадкі"</string>
     <string name="battery_info_status_unknown" msgid="196130600938058547">"Невядома"</string>
     <string name="battery_info_status_charging" msgid="1705179948350365604">"Зарадка"</string>
     <string name="battery_info_status_charging_lower" msgid="8689770213898117994">"ідзе зарадка"</string>
diff --git a/packages/SettingsLib/res/values-bg/strings.xml b/packages/SettingsLib/res/values-bg/strings.xml
index 7fa5b06..cb99f64 100644
--- a/packages/SettingsLib/res/values-bg/strings.xml
+++ b/packages/SettingsLib/res/values-bg/strings.xml
@@ -402,8 +402,8 @@
     <string name="power_remaining_duration_shutdown_imminent" product="tablet" msgid="7466484148515796216">"Възможно е таблетът да се изключи скоро (<xliff:g id="LEVEL">%1$s</xliff:g>)"</string>
     <string name="power_remaining_duration_shutdown_imminent" product="device" msgid="603933521600231649">"Възможно е устройството да се изключи скоро (<xliff:g id="LEVEL">%1$s</xliff:g>)"</string>
     <string name="power_charging" msgid="1779532561355864267">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="STATE">%2$s</xliff:g>"</string>
-    <string name="power_remaining_charging_duration_only" msgid="1421102457410268886">"Оставащо време до пълно зареждане: <xliff:g id="TIME">%1$s</xliff:g>"</string>
-    <string name="power_charging_duration" msgid="4676999980973411875">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g> до пълно зареждане"</string>
+    <string name="power_remaining_charging_duration_only" msgid="6672239353042034265">"Оставащо време до пълно зареждане: <xliff:g id="TIME">%1$s</xliff:g>"</string>
+    <string name="power_charging_duration" msgid="5850751284103249125">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g> до пълно зареждане"</string>
     <string name="battery_info_status_unknown" msgid="196130600938058547">"Неизвестно"</string>
     <string name="battery_info_status_charging" msgid="1705179948350365604">"Зарежда се"</string>
     <string name="battery_info_status_charging_lower" msgid="8689770213898117994">"зарежда се"</string>
diff --git a/packages/SettingsLib/res/values-bn/strings.xml b/packages/SettingsLib/res/values-bn/strings.xml
index f1fc9f9..f2f4f52 100644
--- a/packages/SettingsLib/res/values-bn/strings.xml
+++ b/packages/SettingsLib/res/values-bn/strings.xml
@@ -402,8 +402,8 @@
     <string name="power_remaining_duration_shutdown_imminent" product="tablet" msgid="7466484148515796216">"ট্যাবলেটটি শীঘ্রই বন্ধ হয়ে যেতে পারে (<xliff:g id="LEVEL">%1$s</xliff:g>)"</string>
     <string name="power_remaining_duration_shutdown_imminent" product="device" msgid="603933521600231649">"ডিভাইসটি শীঘ্রই বন্ধ হয়ে যেতে পারে (<xliff:g id="LEVEL">%1$s</xliff:g>)"</string>
     <string name="power_charging" msgid="1779532561355864267">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string>
-    <string name="power_remaining_charging_duration_only" msgid="1421102457410268886">"সম্পূর্ণ চার্জ হতে <xliff:g id="TIME">%1$s</xliff:g> বাকি"</string>
-    <string name="power_charging_duration" msgid="4676999980973411875">"<xliff:g id="LEVEL">%1$s</xliff:g> - সম্পূর্ণ চার্জ হতে <xliff:g id="TIME">%2$s</xliff:g> লাগবে"</string>
+    <string name="power_remaining_charging_duration_only" msgid="6672239353042034265">"সম্পূর্ণ চার্জ হতে <xliff:g id="TIME">%1$s</xliff:g> বাকি আছে"</string>
+    <string name="power_charging_duration" msgid="5850751284103249125">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g>-এ সম্পূর্ণ চার্জ হয়ে যাবে"</string>
     <string name="battery_info_status_unknown" msgid="196130600938058547">"অজানা"</string>
     <string name="battery_info_status_charging" msgid="1705179948350365604">"চার্জ হচ্ছে"</string>
     <string name="battery_info_status_charging_lower" msgid="8689770213898117994">"চার্জ হচ্ছে"</string>
diff --git a/packages/SettingsLib/res/values-bs/strings.xml b/packages/SettingsLib/res/values-bs/strings.xml
index 02b2a8b..45b8dd9 100644
--- a/packages/SettingsLib/res/values-bs/strings.xml
+++ b/packages/SettingsLib/res/values-bs/strings.xml
@@ -402,8 +402,8 @@
     <string name="power_remaining_duration_shutdown_imminent" product="tablet" msgid="7466484148515796216">"Tablet će se uskoro isključiti (<xliff:g id="LEVEL">%1$s</xliff:g>)"</string>
     <string name="power_remaining_duration_shutdown_imminent" product="device" msgid="603933521600231649">"Uređaj će se uskoro isključiti (<xliff:g id="LEVEL">%1$s</xliff:g>)"</string>
     <string name="power_charging" msgid="1779532561355864267">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="STATE">%2$s</xliff:g>"</string>
-    <string name="power_remaining_charging_duration_only" msgid="1421102457410268886">"Još <xliff:g id="TIME">%1$s</xliff:g> do potpune napunjenosti"</string>
-    <string name="power_charging_duration" msgid="4676999980973411875">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> do potpune napunjenosti"</string>
+    <string name="power_remaining_charging_duration_only" msgid="6672239353042034265">"Napunit će se za <xliff:g id="TIME">%1$s</xliff:g>"</string>
+    <string name="power_charging_duration" msgid="5850751284103249125">"<xliff:g id="LEVEL">%1$s</xliff:g> – napunit će se za <xliff:g id="TIME">%2$s</xliff:g>"</string>
     <string name="battery_info_status_unknown" msgid="196130600938058547">"Nepoznato"</string>
     <string name="battery_info_status_charging" msgid="1705179948350365604">"Punjenje"</string>
     <string name="battery_info_status_charging_lower" msgid="8689770213898117994">"punjenje"</string>
diff --git a/packages/SettingsLib/res/values-ca/strings.xml b/packages/SettingsLib/res/values-ca/strings.xml
index 2649544..bd1ed6a 100644
--- a/packages/SettingsLib/res/values-ca/strings.xml
+++ b/packages/SettingsLib/res/values-ca/strings.xml
@@ -402,8 +402,8 @@
     <string name="power_remaining_duration_shutdown_imminent" product="tablet" msgid="7466484148515796216">"És possible que la tauleta s\'apagui aviat (<xliff:g id="LEVEL">%1$s</xliff:g>)"</string>
     <string name="power_remaining_duration_shutdown_imminent" product="device" msgid="603933521600231649">"És possible que el dispositiu s\'apagui aviat (<xliff:g id="LEVEL">%1$s</xliff:g>)"</string>
     <string name="power_charging" msgid="1779532561355864267">"<xliff:g id="LEVEL">%1$s</xliff:g>: <xliff:g id="STATE">%2$s</xliff:g>"</string>
-    <string name="power_remaining_charging_duration_only" msgid="1421102457410268886">"<xliff:g id="TIME">%1$s</xliff:g> per completar la càrrega"</string>
-    <string name="power_charging_duration" msgid="4676999980973411875">"<xliff:g id="LEVEL">%1$s</xliff:g>: <xliff:g id="TIME">%2$s</xliff:g> per completar la càrrega"</string>
+    <string name="power_remaining_charging_duration_only" msgid="6672239353042034265">"<xliff:g id="TIME">%1$s</xliff:g> per completar la càrrega"</string>
+    <string name="power_charging_duration" msgid="5850751284103249125">"<xliff:g id="LEVEL">%1$s</xliff:g>: <xliff:g id="TIME">%2$s</xliff:g> per completar la càrrega"</string>
     <string name="battery_info_status_unknown" msgid="196130600938058547">"Desconegut"</string>
     <string name="battery_info_status_charging" msgid="1705179948350365604">"S\'està carregant"</string>
     <string name="battery_info_status_charging_lower" msgid="8689770213898117994">"s\'està carregant"</string>
diff --git a/packages/SettingsLib/res/values-cs/strings.xml b/packages/SettingsLib/res/values-cs/strings.xml
index 5256399..042e12a 100644
--- a/packages/SettingsLib/res/values-cs/strings.xml
+++ b/packages/SettingsLib/res/values-cs/strings.xml
@@ -402,8 +402,8 @@
     <string name="power_remaining_duration_shutdown_imminent" product="tablet" msgid="7466484148515796216">"Tablet se brzy vypne (<xliff:g id="LEVEL">%1$s</xliff:g>)"</string>
     <string name="power_remaining_duration_shutdown_imminent" product="device" msgid="603933521600231649">"Zařízení se brzy vypne (<xliff:g id="LEVEL">%1$s</xliff:g>)"</string>
     <string name="power_charging" msgid="1779532561355864267">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="STATE">%2$s</xliff:g>"</string>
-    <string name="power_remaining_charging_duration_only" msgid="1421102457410268886">"Plně se nabije za <xliff:g id="TIME">%1$s</xliff:g>"</string>
-    <string name="power_charging_duration" msgid="4676999980973411875">"<xliff:g id="LEVEL">%1$s</xliff:g> – plně se nabije za <xliff:g id="TIME">%2$s</xliff:g>"</string>
+    <string name="power_remaining_charging_duration_only" msgid="6672239353042034265">"Do nabití zbývá: <xliff:g id="TIME">%1$s</xliff:g>"</string>
+    <string name="power_charging_duration" msgid="5850751284103249125">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g> do nabití"</string>
     <string name="battery_info_status_unknown" msgid="196130600938058547">"Neznámé"</string>
     <string name="battery_info_status_charging" msgid="1705179948350365604">"Nabíjí se"</string>
     <string name="battery_info_status_charging_lower" msgid="8689770213898117994">"nabíjení"</string>
diff --git a/packages/SettingsLib/res/values-da/strings.xml b/packages/SettingsLib/res/values-da/strings.xml
index 1884f64..4723293 100644
--- a/packages/SettingsLib/res/values-da/strings.xml
+++ b/packages/SettingsLib/res/values-da/strings.xml
@@ -402,8 +402,8 @@
     <string name="power_remaining_duration_shutdown_imminent" product="tablet" msgid="7466484148515796216">"Denne tablet lukker muligvis snart ned (<xliff:g id="LEVEL">%1$s</xliff:g>)"</string>
     <string name="power_remaining_duration_shutdown_imminent" product="device" msgid="603933521600231649">"Enheden lukker muligvis snart ned (<xliff:g id="LEVEL">%1$s</xliff:g>)"</string>
     <string name="power_charging" msgid="1779532561355864267">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="STATE">%2$s</xliff:g>"</string>
-    <string name="power_remaining_charging_duration_only" msgid="1421102457410268886">"fuldt opladet om <xliff:g id="TIME">%1$s</xliff:g>"</string>
-    <string name="power_charging_duration" msgid="4676999980973411875">"<xliff:g id="LEVEL">%1$s</xliff:g> – fuldt opladet om <xliff:g id="TIME">%2$s</xliff:g>"</string>
+    <string name="power_remaining_charging_duration_only" msgid="6672239353042034265">"Opladet om <xliff:g id="TIME">%1$s</xliff:g>"</string>
+    <string name="power_charging_duration" msgid="5850751284103249125">"<xliff:g id="LEVEL">%1$s</xliff:g> – opladet om <xliff:g id="TIME">%2$s</xliff:g>"</string>
     <string name="battery_info_status_unknown" msgid="196130600938058547">"Ukendt"</string>
     <string name="battery_info_status_charging" msgid="1705179948350365604">"Oplader"</string>
     <string name="battery_info_status_charging_lower" msgid="8689770213898117994">"oplader"</string>
diff --git a/packages/SettingsLib/res/values-de/strings.xml b/packages/SettingsLib/res/values-de/strings.xml
index d8da638..4f5a965 100644
--- a/packages/SettingsLib/res/values-de/strings.xml
+++ b/packages/SettingsLib/res/values-de/strings.xml
@@ -402,8 +402,8 @@
     <string name="power_remaining_duration_shutdown_imminent" product="tablet" msgid="7466484148515796216">"Tablet wird eventuell bald ausgeschaltet (<xliff:g id="LEVEL">%1$s</xliff:g>)"</string>
     <string name="power_remaining_duration_shutdown_imminent" product="device" msgid="603933521600231649">"Gerät wird eventuell bald ausgeschaltet (<xliff:g id="LEVEL">%1$s</xliff:g>)"</string>
     <string name="power_charging" msgid="1779532561355864267">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="STATE">%2$s</xliff:g>"</string>
-    <string name="power_remaining_charging_duration_only" msgid="1421102457410268886">"<xliff:g id="TIME">%1$s</xliff:g> bis zur vollständigen Aufladung"</string>
-    <string name="power_charging_duration" msgid="4676999980973411875">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g> bis vollständig geladen"</string>
+    <string name="power_remaining_charging_duration_only" msgid="6672239353042034265">"Noch <xliff:g id="TIME">%1$s</xliff:g> bis zur Aufladung"</string>
+    <string name="power_charging_duration" msgid="5850751284103249125">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g> bis zur Aufladung"</string>
     <string name="battery_info_status_unknown" msgid="196130600938058547">"Unbekannt"</string>
     <string name="battery_info_status_charging" msgid="1705179948350365604">"Wird aufgeladen"</string>
     <string name="battery_info_status_charging_lower" msgid="8689770213898117994">"wird aufgeladen..."</string>
diff --git a/packages/SettingsLib/res/values-el/strings.xml b/packages/SettingsLib/res/values-el/strings.xml
index b1b1be6..753dea8 100644
--- a/packages/SettingsLib/res/values-el/strings.xml
+++ b/packages/SettingsLib/res/values-el/strings.xml
@@ -402,8 +402,8 @@
     <string name="power_remaining_duration_shutdown_imminent" product="tablet" msgid="7466484148515796216">"Το tablet μπορεί να απενεργοποιηθεί σύντομα (<xliff:g id="LEVEL">%1$s</xliff:g>)"</string>
     <string name="power_remaining_duration_shutdown_imminent" product="device" msgid="603933521600231649">"Η συσκευή μπορεί να απενεργοποιηθεί σύντομα (<xliff:g id="LEVEL">%1$s</xliff:g>)"</string>
     <string name="power_charging" msgid="1779532561355864267">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string>
-    <string name="power_remaining_charging_duration_only" msgid="1421102457410268886">"Απομένουν <xliff:g id="TIME">%1$s</xliff:g> έως την πλήρη φόρτιση"</string>
-    <string name="power_charging_duration" msgid="4676999980973411875">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> για πλήρη φόρτιση"</string>
+    <string name="power_remaining_charging_duration_only" msgid="6672239353042034265">"Απομένουν <xliff:g id="TIME">%1$s</xliff:g> για ολοκλήρωση της φόρτισης"</string>
+    <string name="power_charging_duration" msgid="5850751284103249125">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> για την ολοκλήρωση της φόρτισης"</string>
     <string name="battery_info_status_unknown" msgid="196130600938058547">"Άγνωστο"</string>
     <string name="battery_info_status_charging" msgid="1705179948350365604">"Φόρτιση"</string>
     <string name="battery_info_status_charging_lower" msgid="8689770213898117994">"φόρτιση"</string>
diff --git a/packages/SettingsLib/res/values-en-rAU/strings.xml b/packages/SettingsLib/res/values-en-rAU/strings.xml
index 63463b1..dd3d278 100644
--- a/packages/SettingsLib/res/values-en-rAU/strings.xml
+++ b/packages/SettingsLib/res/values-en-rAU/strings.xml
@@ -402,8 +402,8 @@
     <string name="power_remaining_duration_shutdown_imminent" product="tablet" msgid="7466484148515796216">"Tablet may shutdown soon (<xliff:g id="LEVEL">%1$s</xliff:g>)"</string>
     <string name="power_remaining_duration_shutdown_imminent" product="device" msgid="603933521600231649">"Device may shutdown soon (<xliff:g id="LEVEL">%1$s</xliff:g>)"</string>
     <string name="power_charging" msgid="1779532561355864267">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string>
-    <string name="power_remaining_charging_duration_only" msgid="1421102457410268886">"<xliff:g id="TIME">%1$s</xliff:g> left until fully charged"</string>
-    <string name="power_charging_duration" msgid="4676999980973411875">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g> until fully charged"</string>
+    <string name="power_remaining_charging_duration_only" msgid="6672239353042034265">"<xliff:g id="TIME">%1$s</xliff:g> left until charged"</string>
+    <string name="power_charging_duration" msgid="5850751284103249125">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> until charged"</string>
     <string name="battery_info_status_unknown" msgid="196130600938058547">"Unknown"</string>
     <string name="battery_info_status_charging" msgid="1705179948350365604">"Charging"</string>
     <string name="battery_info_status_charging_lower" msgid="8689770213898117994">"charging"</string>
diff --git a/packages/SettingsLib/res/values-en-rCA/strings.xml b/packages/SettingsLib/res/values-en-rCA/strings.xml
index 63463b1..dd3d278 100644
--- a/packages/SettingsLib/res/values-en-rCA/strings.xml
+++ b/packages/SettingsLib/res/values-en-rCA/strings.xml
@@ -402,8 +402,8 @@
     <string name="power_remaining_duration_shutdown_imminent" product="tablet" msgid="7466484148515796216">"Tablet may shutdown soon (<xliff:g id="LEVEL">%1$s</xliff:g>)"</string>
     <string name="power_remaining_duration_shutdown_imminent" product="device" msgid="603933521600231649">"Device may shutdown soon (<xliff:g id="LEVEL">%1$s</xliff:g>)"</string>
     <string name="power_charging" msgid="1779532561355864267">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string>
-    <string name="power_remaining_charging_duration_only" msgid="1421102457410268886">"<xliff:g id="TIME">%1$s</xliff:g> left until fully charged"</string>
-    <string name="power_charging_duration" msgid="4676999980973411875">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g> until fully charged"</string>
+    <string name="power_remaining_charging_duration_only" msgid="6672239353042034265">"<xliff:g id="TIME">%1$s</xliff:g> left until charged"</string>
+    <string name="power_charging_duration" msgid="5850751284103249125">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> until charged"</string>
     <string name="battery_info_status_unknown" msgid="196130600938058547">"Unknown"</string>
     <string name="battery_info_status_charging" msgid="1705179948350365604">"Charging"</string>
     <string name="battery_info_status_charging_lower" msgid="8689770213898117994">"charging"</string>
diff --git a/packages/SettingsLib/res/values-en-rGB/strings.xml b/packages/SettingsLib/res/values-en-rGB/strings.xml
index 63463b1..dd3d278 100644
--- a/packages/SettingsLib/res/values-en-rGB/strings.xml
+++ b/packages/SettingsLib/res/values-en-rGB/strings.xml
@@ -402,8 +402,8 @@
     <string name="power_remaining_duration_shutdown_imminent" product="tablet" msgid="7466484148515796216">"Tablet may shutdown soon (<xliff:g id="LEVEL">%1$s</xliff:g>)"</string>
     <string name="power_remaining_duration_shutdown_imminent" product="device" msgid="603933521600231649">"Device may shutdown soon (<xliff:g id="LEVEL">%1$s</xliff:g>)"</string>
     <string name="power_charging" msgid="1779532561355864267">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string>
-    <string name="power_remaining_charging_duration_only" msgid="1421102457410268886">"<xliff:g id="TIME">%1$s</xliff:g> left until fully charged"</string>
-    <string name="power_charging_duration" msgid="4676999980973411875">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g> until fully charged"</string>
+    <string name="power_remaining_charging_duration_only" msgid="6672239353042034265">"<xliff:g id="TIME">%1$s</xliff:g> left until charged"</string>
+    <string name="power_charging_duration" msgid="5850751284103249125">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> until charged"</string>
     <string name="battery_info_status_unknown" msgid="196130600938058547">"Unknown"</string>
     <string name="battery_info_status_charging" msgid="1705179948350365604">"Charging"</string>
     <string name="battery_info_status_charging_lower" msgid="8689770213898117994">"charging"</string>
diff --git a/packages/SettingsLib/res/values-en-rIN/strings.xml b/packages/SettingsLib/res/values-en-rIN/strings.xml
index 63463b1..dd3d278 100644
--- a/packages/SettingsLib/res/values-en-rIN/strings.xml
+++ b/packages/SettingsLib/res/values-en-rIN/strings.xml
@@ -402,8 +402,8 @@
     <string name="power_remaining_duration_shutdown_imminent" product="tablet" msgid="7466484148515796216">"Tablet may shutdown soon (<xliff:g id="LEVEL">%1$s</xliff:g>)"</string>
     <string name="power_remaining_duration_shutdown_imminent" product="device" msgid="603933521600231649">"Device may shutdown soon (<xliff:g id="LEVEL">%1$s</xliff:g>)"</string>
     <string name="power_charging" msgid="1779532561355864267">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string>
-    <string name="power_remaining_charging_duration_only" msgid="1421102457410268886">"<xliff:g id="TIME">%1$s</xliff:g> left until fully charged"</string>
-    <string name="power_charging_duration" msgid="4676999980973411875">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g> until fully charged"</string>
+    <string name="power_remaining_charging_duration_only" msgid="6672239353042034265">"<xliff:g id="TIME">%1$s</xliff:g> left until charged"</string>
+    <string name="power_charging_duration" msgid="5850751284103249125">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> until charged"</string>
     <string name="battery_info_status_unknown" msgid="196130600938058547">"Unknown"</string>
     <string name="battery_info_status_charging" msgid="1705179948350365604">"Charging"</string>
     <string name="battery_info_status_charging_lower" msgid="8689770213898117994">"charging"</string>
diff --git a/packages/SettingsLib/res/values-en-rXC/strings.xml b/packages/SettingsLib/res/values-en-rXC/strings.xml
index e5a0bda..d9f61d8 100644
--- a/packages/SettingsLib/res/values-en-rXC/strings.xml
+++ b/packages/SettingsLib/res/values-en-rXC/strings.xml
@@ -402,8 +402,8 @@
     <string name="power_remaining_duration_shutdown_imminent" product="tablet" msgid="7466484148515796216">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‏‏‏‏‏‎‎‏‏‏‏‎‎‏‏‏‏‎‎‏‎‎‎‏‏‏‏‏‎‎‎‏‏‎‎‎‏‎‎‎‎‏‎‏‎‏‏‏‏‎‎‏‏‏‎‏‎‎‏‏‏‏‏‎‎‎‎Tablet may shutdown soon (‎‏‎‎‏‏‎<xliff:g id="LEVEL">%1$s</xliff:g>‎‏‎‎‏‏‏‎)‎‏‎‎‏‎"</string>
     <string name="power_remaining_duration_shutdown_imminent" product="device" msgid="603933521600231649">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‏‎‎‏‎‎‎‎‏‏‎‎‎‎‏‏‎‎‏‏‎‏‎‎‏‎‏‎‏‏‎‏‎‎‎‏‏‏‎‏‏‏‎‏‏‏‎‏‎‏‏‏‎‎‎‏‏‏‎‎‎‎‏‎Device may shutdown soon (‎‏‎‎‏‏‎<xliff:g id="LEVEL">%1$s</xliff:g>‎‏‎‎‏‏‏‎)‎‏‎‎‏‎"</string>
     <string name="power_charging" msgid="1779532561355864267">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‏‎‏‏‏‎‎‎‏‎‏‏‎‎‏‎‎‎‏‎‏‎‏‏‎‏‏‎‏‏‏‏‏‎‏‎‏‎‎‏‏‏‎‏‏‎‏‏‎‏‏‏‏‎‎‎‏‏‎‎‏‎‏‏‎‎‏‎‎‏‏‎<xliff:g id="LEVEL">%1$s</xliff:g>‎‏‎‎‏‏‏‎ - ‎‏‎‎‏‏‎<xliff:g id="STATE">%2$s</xliff:g>‎‏‎‎‏‏‏‎‎‏‎‎‏‎"</string>
-    <string name="power_remaining_charging_duration_only" msgid="1421102457410268886">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‏‎‏‏‎‎‏‏‏‎‏‏‏‎‎‎‏‏‎‎‎‏‎‏‎‎‏‎‎‏‏‏‏‏‎‏‏‎‏‏‎‏‎‏‏‏‏‏‏‎‏‎‏‏‏‎‏‏‎‏‎‏‏‎‎‎‏‎‎‏‏‎<xliff:g id="TIME">%1$s</xliff:g>‎‏‎‎‏‏‏‎ left until fully charged‎‏‎‎‏‎"</string>
-    <string name="power_charging_duration" msgid="4676999980973411875">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‏‏‏‏‎‎‎‎‎‎‏‏‏‎‏‎‎‎‎‎‎‎‏‎‏‎‏‎‏‏‎‎‏‏‏‏‏‏‎‎‎‎‎‏‏‎‏‏‎‏‏‏‎‎‏‏‏‎‎‎‏‎‎‎‏‏‎‎‏‎‎‏‏‎<xliff:g id="LEVEL">%1$s</xliff:g>‎‏‎‎‏‏‏‎ - ‎‏‎‎‏‏‎<xliff:g id="TIME">%2$s</xliff:g>‎‏‎‎‏‏‏‎ until fully charged‎‏‎‎‏‎"</string>
+    <string name="power_remaining_charging_duration_only" msgid="6672239353042034265">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‏‏‏‏‎‏‏‏‎‎‏‎‎‏‏‎‎‎‏‎‎‎‏‏‏‎‎‏‎‏‎‏‏‏‎‎‏‎‏‏‏‎‎‏‏‏‎‎‏‏‏‏‎‏‏‏‏‎‎‏‎‏‏‎‎‏‎‎‏‎‎‏‏‎<xliff:g id="TIME">%1$s</xliff:g>‎‏‎‎‏‏‏‎ left until charged‎‏‎‎‏‎"</string>
+    <string name="power_charging_duration" msgid="5850751284103249125">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‏‏‏‏‎‏‎‎‎‏‎‎‏‏‎‎‏‎‎‎‎‎‏‎‏‏‎‏‎‎‏‎‏‏‎‏‎‏‎‏‏‎‎‎‏‎‎‎‏‎‎‏‏‏‏‏‎‎‏‏‏‎‎‏‎‏‎‎‏‎‎‏‏‎<xliff:g id="LEVEL">%1$s</xliff:g>‎‏‎‎‏‏‏‎ - ‎‏‎‎‏‏‎<xliff:g id="TIME">%2$s</xliff:g>‎‏‎‎‏‏‏‎ until charged‎‏‎‎‏‎"</string>
     <string name="battery_info_status_unknown" msgid="196130600938058547">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‎‏‎‏‎‏‎‏‏‏‎‎‎‏‏‎‎‏‎‏‏‏‎‏‏‏‏‏‎‎‎‎‎‏‏‏‎‎‏‏‏‏‏‏‏‎‎‏‏‎‎‏‏‎‎‏‏‎‎‏‏‎Unknown‎‏‎‎‏‎"</string>
     <string name="battery_info_status_charging" msgid="1705179948350365604">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‏‎‏‏‎‏‏‏‏‎‏‎‏‎‏‎‎‎‎‎‎‏‎‎‎‎‏‎‎‎‎‎‏‏‏‎‏‎‏‏‏‎‎‎‏‎‏‎‏‏‎‏‏‏‏‏‏‎‏‎‎‏‎‎‎Charging‎‏‎‎‏‎"</string>
     <string name="battery_info_status_charging_lower" msgid="8689770213898117994">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‏‏‏‏‏‏‏‎‎‎‏‎‎‏‏‎‎‎‎‏‎‎‎‎‏‏‏‏‏‏‏‎‎‎‎‎‎‏‏‎‏‏‎‎‏‎‏‎‏‎‏‏‏‎‎‎‏‏‎‏‏‎‏‎‏‎‎charging‎‏‎‎‏‎"</string>
diff --git a/packages/SettingsLib/res/values-es-rUS/strings.xml b/packages/SettingsLib/res/values-es-rUS/strings.xml
index 7874aeb..30cb0a1 100644
--- a/packages/SettingsLib/res/values-es-rUS/strings.xml
+++ b/packages/SettingsLib/res/values-es-rUS/strings.xml
@@ -402,8 +402,8 @@
     <string name="power_remaining_duration_shutdown_imminent" product="tablet" msgid="7466484148515796216">"Es posible que pronto se apague la tablet (<xliff:g id="LEVEL">%1$s</xliff:g>)"</string>
     <string name="power_remaining_duration_shutdown_imminent" product="device" msgid="603933521600231649">"Es posible que pronto se apague el dispositivo (<xliff:g id="LEVEL">%1$s</xliff:g>)"</string>
     <string name="power_charging" msgid="1779532561355864267">"<xliff:g id="LEVEL">%1$s</xliff:g>: <xliff:g id="STATE">%2$s</xliff:g>"</string>
-    <string name="power_remaining_charging_duration_only" msgid="1421102457410268886">"<xliff:g id="TIME">%1$s</xliff:g> para completar la carga"</string>
-    <string name="power_charging_duration" msgid="4676999980973411875">"<xliff:g id="LEVEL">%1$s</xliff:g> (<xliff:g id="TIME">%2$s</xliff:g> para completar la carga)"</string>
+    <string name="power_remaining_charging_duration_only" msgid="6672239353042034265">"<xliff:g id="TIME">%1$s</xliff:g> para completar la carga"</string>
+    <string name="power_charging_duration" msgid="5850751284103249125">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> para completar la carga"</string>
     <string name="battery_info_status_unknown" msgid="196130600938058547">"Desconocido"</string>
     <string name="battery_info_status_charging" msgid="1705179948350365604">"Cargando"</string>
     <string name="battery_info_status_charging_lower" msgid="8689770213898117994">"cargando"</string>
diff --git a/packages/SettingsLib/res/values-es/strings.xml b/packages/SettingsLib/res/values-es/strings.xml
index 8baf7a2..32905df 100644
--- a/packages/SettingsLib/res/values-es/strings.xml
+++ b/packages/SettingsLib/res/values-es/strings.xml
@@ -402,8 +402,8 @@
     <string name="power_remaining_duration_shutdown_imminent" product="tablet" msgid="7466484148515796216">"Es posible que el tablet se apague pronto (<xliff:g id="LEVEL">%1$s</xliff:g>)"</string>
     <string name="power_remaining_duration_shutdown_imminent" product="device" msgid="603933521600231649">"Es posible que el dispositivo se apague pronto (<xliff:g id="LEVEL">%1$s</xliff:g>)"</string>
     <string name="power_charging" msgid="1779532561355864267">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string>
-    <string name="power_remaining_charging_duration_only" msgid="1421102457410268886">"Tiempo restante hasta carga completa: <xliff:g id="TIME">%1$s</xliff:g>"</string>
-    <string name="power_charging_duration" msgid="4676999980973411875">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> para completar la carga"</string>
+    <string name="power_remaining_charging_duration_only" msgid="6672239353042034265">"<xliff:g id="TIME">%1$s</xliff:g> hasta que termine de cargarse"</string>
+    <string name="power_charging_duration" msgid="5850751284103249125">"<xliff:g id="LEVEL">%1$s</xliff:g> (<xliff:g id="TIME">%2$s</xliff:g> hasta que termine de cargarse)"</string>
     <string name="battery_info_status_unknown" msgid="196130600938058547">"Desconocido"</string>
     <string name="battery_info_status_charging" msgid="1705179948350365604">"Cargando"</string>
     <string name="battery_info_status_charging_lower" msgid="8689770213898117994">"cargando"</string>
diff --git a/packages/SettingsLib/res/values-et/strings.xml b/packages/SettingsLib/res/values-et/strings.xml
index 090b28d..79b8a84 100644
--- a/packages/SettingsLib/res/values-et/strings.xml
+++ b/packages/SettingsLib/res/values-et/strings.xml
@@ -402,8 +402,8 @@
     <string name="power_remaining_duration_shutdown_imminent" product="tablet" msgid="7466484148515796216">"Tahvelarvuti võib peagi välja lülituda (<xliff:g id="LEVEL">%1$s</xliff:g>)"</string>
     <string name="power_remaining_duration_shutdown_imminent" product="device" msgid="603933521600231649">"Seade võib peagi välja lülituda (<xliff:g id="LEVEL">%1$s</xliff:g>)"</string>
     <string name="power_charging" msgid="1779532561355864267">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="STATE">%2$s</xliff:g>"</string>
-    <string name="power_remaining_charging_duration_only" msgid="1421102457410268886">"<xliff:g id="TIME">%1$s</xliff:g> täislaadimiseni"</string>
-    <string name="power_charging_duration" msgid="4676999980973411875">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g> täislaadimiseni"</string>
+    <string name="power_remaining_charging_duration_only" msgid="6672239353042034265">"Täislaadimiseni on jäänud <xliff:g id="TIME">%1$s</xliff:g>"</string>
+    <string name="power_charging_duration" msgid="5850751284103249125">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g> täislaadimiseni"</string>
     <string name="battery_info_status_unknown" msgid="196130600938058547">"Tundmatu"</string>
     <string name="battery_info_status_charging" msgid="1705179948350365604">"Laadimine"</string>
     <string name="battery_info_status_charging_lower" msgid="8689770213898117994">"laadimine"</string>
diff --git a/packages/SettingsLib/res/values-eu/strings.xml b/packages/SettingsLib/res/values-eu/strings.xml
index fd3936d..bab4cde 100644
--- a/packages/SettingsLib/res/values-eu/strings.xml
+++ b/packages/SettingsLib/res/values-eu/strings.xml
@@ -402,8 +402,8 @@
     <string name="power_remaining_duration_shutdown_imminent" product="tablet" msgid="7466484148515796216">"Baliteke tableta laster itzaltzea (<xliff:g id="LEVEL">%1$s</xliff:g>)"</string>
     <string name="power_remaining_duration_shutdown_imminent" product="device" msgid="603933521600231649">"Baliteke gailua laster itzaltzea (<xliff:g id="LEVEL">%1$s</xliff:g>)"</string>
     <string name="power_charging" msgid="1779532561355864267">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string>
-    <string name="power_remaining_charging_duration_only" msgid="1421102457410268886">"<xliff:g id="TIME">%1$s</xliff:g> falta dira guztiz kargatu arte"</string>
-    <string name="power_charging_duration" msgid="4676999980973411875">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> guztiz kargatu arte"</string>
+    <string name="power_remaining_charging_duration_only" msgid="6672239353042034265">"<xliff:g id="TIME">%1$s</xliff:g> guztiz kargatu arte"</string>
+    <string name="power_charging_duration" msgid="5850751284103249125">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> guztiz kargatu arte"</string>
     <string name="battery_info_status_unknown" msgid="196130600938058547">"Ezezaguna"</string>
     <string name="battery_info_status_charging" msgid="1705179948350365604">"Kargatzen"</string>
     <string name="battery_info_status_charging_lower" msgid="8689770213898117994">"kargatzen"</string>
diff --git a/packages/SettingsLib/res/values-fa/strings.xml b/packages/SettingsLib/res/values-fa/strings.xml
index 352c276..9d84090 100644
--- a/packages/SettingsLib/res/values-fa/strings.xml
+++ b/packages/SettingsLib/res/values-fa/strings.xml
@@ -402,8 +402,8 @@
     <string name="power_remaining_duration_shutdown_imminent" product="tablet" msgid="7466484148515796216">"ممکن است رایانه لوحی به‌زودی خاموش شود (<xliff:g id="LEVEL">%1$s</xliff:g>)"</string>
     <string name="power_remaining_duration_shutdown_imminent" product="device" msgid="603933521600231649">"ممکن است دستگاه به‌زودی خاموش شود (<xliff:g id="LEVEL">%1$s</xliff:g>)"</string>
     <string name="power_charging" msgid="1779532561355864267">"<xliff:g id="LEVEL">%1$s</xliff:g> - ‏<xliff:g id="STATE">%2$s</xliff:g>"</string>
-    <string name="power_remaining_charging_duration_only" msgid="1421102457410268886">"<xliff:g id="TIME">%1$s</xliff:g> تا شارژ شدن کامل باقی مانده است"</string>
-    <string name="power_charging_duration" msgid="4676999980973411875">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> مانده تا شارژ کامل"</string>
+    <string name="power_remaining_charging_duration_only" msgid="6672239353042034265">"<xliff:g id="TIME">%1$s</xliff:g> مانده تا شارژ کامل"</string>
+    <string name="power_charging_duration" msgid="5850751284103249125">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> تا شارژ کامل"</string>
     <string name="battery_info_status_unknown" msgid="196130600938058547">"ناشناس"</string>
     <string name="battery_info_status_charging" msgid="1705179948350365604">"در حال شارژ شدن"</string>
     <string name="battery_info_status_charging_lower" msgid="8689770213898117994">"درحال شارژ شدن"</string>
diff --git a/packages/SettingsLib/res/values-fi/strings.xml b/packages/SettingsLib/res/values-fi/strings.xml
index 0d522c4..929e101 100644
--- a/packages/SettingsLib/res/values-fi/strings.xml
+++ b/packages/SettingsLib/res/values-fi/strings.xml
@@ -402,8 +402,8 @@
     <string name="power_remaining_duration_shutdown_imminent" product="tablet" msgid="7466484148515796216">"Tabletti voi pian sammua (<xliff:g id="LEVEL">%1$s</xliff:g>)"</string>
     <string name="power_remaining_duration_shutdown_imminent" product="device" msgid="603933521600231649">"Laite voi pian sammua (<xliff:g id="LEVEL">%1$s</xliff:g>)"</string>
     <string name="power_charging" msgid="1779532561355864267">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="STATE">%2$s</xliff:g>"</string>
-    <string name="power_remaining_charging_duration_only" msgid="1421102457410268886">"<xliff:g id="TIME">%1$s</xliff:g> kunnes täynnä"</string>
-    <string name="power_charging_duration" msgid="4676999980973411875">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g> täyteen lataukseen"</string>
+    <string name="power_remaining_charging_duration_only" msgid="6672239353042034265">"<xliff:g id="TIME">%1$s</xliff:g> jäljellä täyteen lataukseen"</string>
+    <string name="power_charging_duration" msgid="5850751284103249125">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g> täyteen lataukseen"</string>
     <string name="battery_info_status_unknown" msgid="196130600938058547">"Tuntematon"</string>
     <string name="battery_info_status_charging" msgid="1705179948350365604">"Ladataan"</string>
     <string name="battery_info_status_charging_lower" msgid="8689770213898117994">"ladataan"</string>
diff --git a/packages/SettingsLib/res/values-fr-rCA/strings.xml b/packages/SettingsLib/res/values-fr-rCA/strings.xml
index 1dde863..d3bfc96 100644
--- a/packages/SettingsLib/res/values-fr-rCA/strings.xml
+++ b/packages/SettingsLib/res/values-fr-rCA/strings.xml
@@ -402,8 +402,8 @@
     <string name="power_remaining_duration_shutdown_imminent" product="tablet" msgid="7466484148515796216">"Il se peut que la tablette s\'éteigne bientôt (<xliff:g id="LEVEL">%1$s</xliff:g>)"</string>
     <string name="power_remaining_duration_shutdown_imminent" product="device" msgid="603933521600231649">"Il se peut que l\'appareil s\'éteigne bientôt (<xliff:g id="LEVEL">%1$s</xliff:g>)"</string>
     <string name="power_charging" msgid="1779532561355864267">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string>
-    <string name="power_remaining_charging_duration_only" msgid="1421102457410268886">"<xliff:g id="TIME">%1$s</xliff:g> jusqu\'à la charge complète"</string>
-    <string name="power_charging_duration" msgid="4676999980973411875">"<xliff:g id="LEVEL">%1$s</xliff:g> : <xliff:g id="TIME">%2$s</xliff:g> jusqu\'à la charge complète"</string>
+    <string name="power_remaining_charging_duration_only" msgid="6672239353042034265">"<xliff:g id="TIME">%1$s</xliff:g> jusqu\'à la charge complète"</string>
+    <string name="power_charging_duration" msgid="5850751284103249125">"<xliff:g id="LEVEL">%1$s</xliff:g> : <xliff:g id="TIME">%2$s</xliff:g> jusqu\'à la charge complète"</string>
     <string name="battery_info_status_unknown" msgid="196130600938058547">"Inconnu"</string>
     <string name="battery_info_status_charging" msgid="1705179948350365604">"Charge en cours…"</string>
     <string name="battery_info_status_charging_lower" msgid="8689770213898117994">"en cours de charge"</string>
diff --git a/packages/SettingsLib/res/values-fr/strings.xml b/packages/SettingsLib/res/values-fr/strings.xml
index cf4ee13..b5706ce 100644
--- a/packages/SettingsLib/res/values-fr/strings.xml
+++ b/packages/SettingsLib/res/values-fr/strings.xml
@@ -402,8 +402,8 @@
     <string name="power_remaining_duration_shutdown_imminent" product="tablet" msgid="7466484148515796216">"Il est possible que la tablette s\'éteigne bientôt (<xliff:g id="LEVEL">%1$s</xliff:g>)"</string>
     <string name="power_remaining_duration_shutdown_imminent" product="device" msgid="603933521600231649">"Il est possible que l\'appareil s\'éteigne bientôt (<xliff:g id="LEVEL">%1$s</xliff:g>)"</string>
     <string name="power_charging" msgid="1779532561355864267">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="STATE">%2$s</xliff:g>"</string>
-    <string name="power_remaining_charging_duration_only" msgid="1421102457410268886">"<xliff:g id="TIME">%1$s</xliff:g> avant charge complète"</string>
-    <string name="power_charging_duration" msgid="4676999980973411875">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> jusqu\'à la charge complète"</string>
+    <string name="power_remaining_charging_duration_only" msgid="6672239353042034265">"<xliff:g id="TIME">%1$s</xliff:g> jusqu\'à ce que la batterie soit chargée"</string>
+    <string name="power_charging_duration" msgid="5850751284103249125">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> jusqu\'à la charge complète"</string>
     <string name="battery_info_status_unknown" msgid="196130600938058547">"Inconnu"</string>
     <string name="battery_info_status_charging" msgid="1705179948350365604">"Batterie en charge"</string>
     <string name="battery_info_status_charging_lower" msgid="8689770213898117994">"en charge…"</string>
diff --git a/packages/SettingsLib/res/values-gl/strings.xml b/packages/SettingsLib/res/values-gl/strings.xml
index b998a74..2aa1604 100644
--- a/packages/SettingsLib/res/values-gl/strings.xml
+++ b/packages/SettingsLib/res/values-gl/strings.xml
@@ -402,8 +402,8 @@
     <string name="power_remaining_duration_shutdown_imminent" product="tablet" msgid="7466484148515796216">"É posible que a tableta se apague en breve (<xliff:g id="LEVEL">%1$s</xliff:g>)"</string>
     <string name="power_remaining_duration_shutdown_imminent" product="device" msgid="603933521600231649">"É posible que o dispositivo se apague en breve (<xliff:g id="LEVEL">%1$s</xliff:g>)"</string>
     <string name="power_charging" msgid="1779532561355864267">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string>
-    <string name="power_remaining_charging_duration_only" msgid="1421102457410268886">"Tempo que queda para completar a carga: <xliff:g id="TIME">%1$s</xliff:g>"</string>
-    <string name="power_charging_duration" msgid="4676999980973411875">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> para completar a carga"</string>
+    <string name="power_remaining_charging_duration_only" msgid="6672239353042034265">"<xliff:g id="TIME">%1$s</xliff:g> para completar a carga"</string>
+    <string name="power_charging_duration" msgid="5850751284103249125">"<xliff:g id="LEVEL">%1$s</xliff:g>: <xliff:g id="TIME">%2$s</xliff:g> para completar a carga"</string>
     <string name="battery_info_status_unknown" msgid="196130600938058547">"Descoñecido"</string>
     <string name="battery_info_status_charging" msgid="1705179948350365604">"Cargando"</string>
     <string name="battery_info_status_charging_lower" msgid="8689770213898117994">"cargando"</string>
diff --git a/packages/SettingsLib/res/values-gu/strings.xml b/packages/SettingsLib/res/values-gu/strings.xml
index cf0e201..c2cc4c5 100644
--- a/packages/SettingsLib/res/values-gu/strings.xml
+++ b/packages/SettingsLib/res/values-gu/strings.xml
@@ -402,8 +402,8 @@
     <string name="power_remaining_duration_shutdown_imminent" product="tablet" msgid="7466484148515796216">"ટૅબ્લેટ થોડીક જ વારમાં બંધ થઈ શકે છે (<xliff:g id="LEVEL">%1$s</xliff:g>)"</string>
     <string name="power_remaining_duration_shutdown_imminent" product="device" msgid="603933521600231649">"ઉપકરણ થોડીક જ વારમાં બંધ થઈ શકે છે (<xliff:g id="LEVEL">%1$s</xliff:g>)"</string>
     <string name="power_charging" msgid="1779532561355864267">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string>
-    <string name="power_remaining_charging_duration_only" msgid="1421102457410268886">"સંપૂર્ણપણે ચાર્જ થવામાં <xliff:g id="TIME">%1$s</xliff:g> બાકી"</string>
-    <string name="power_charging_duration" msgid="4676999980973411875">"<xliff:g id="LEVEL">%1$s</xliff:g> - સંપૂર્ણપણે ચાર્જ થવા માટે <xliff:g id="TIME">%2$s</xliff:g>"</string>
+    <string name="power_remaining_charging_duration_only" msgid="6672239353042034265">"ચાર્જ થવામાં <xliff:g id="TIME">%1$s</xliff:g> બાકી છે"</string>
+    <string name="power_charging_duration" msgid="5850751284103249125">"<xliff:g id="LEVEL">%1$s</xliff:g> - ચાર્જ થવા માટે <xliff:g id="TIME">%2$s</xliff:g>"</string>
     <string name="battery_info_status_unknown" msgid="196130600938058547">"અજાણ્યું"</string>
     <string name="battery_info_status_charging" msgid="1705179948350365604">"ચાર્જ થઈ રહ્યું છે"</string>
     <string name="battery_info_status_charging_lower" msgid="8689770213898117994">"ચાર્જ થઈ રહ્યું છે"</string>
diff --git a/packages/SettingsLib/res/values-hi/strings.xml b/packages/SettingsLib/res/values-hi/strings.xml
index 3a20d04..61e1997 100644
--- a/packages/SettingsLib/res/values-hi/strings.xml
+++ b/packages/SettingsLib/res/values-hi/strings.xml
@@ -402,8 +402,8 @@
     <string name="power_remaining_duration_shutdown_imminent" product="tablet" msgid="7466484148515796216">"टैबलेट जल्दी ही बंद हो सकता है (<xliff:g id="LEVEL">%1$s</xliff:g>)"</string>
     <string name="power_remaining_duration_shutdown_imminent" product="device" msgid="603933521600231649">"डिवाइस जल्दी ही बंद हो सकता है (<xliff:g id="LEVEL">%1$s</xliff:g>)"</string>
     <string name="power_charging" msgid="1779532561355864267">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string>
-    <string name="power_remaining_charging_duration_only" msgid="1421102457410268886">"पूरी तरह से चार्ज होने में <xliff:g id="TIME">%1$s</xliff:g> शेष"</string>
-    <string name="power_charging_duration" msgid="4676999980973411875">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> पूरी तरह से चार्ज होने तक"</string>
+    <string name="power_remaining_charging_duration_only" msgid="6672239353042034265">"चार्ज पूरा होने में <xliff:g id="TIME">%1$s</xliff:g> बचा है"</string>
+    <string name="power_charging_duration" msgid="5850751284103249125">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> में पूरा चार्ज हो जाएगा"</string>
     <string name="battery_info_status_unknown" msgid="196130600938058547">"अज्ञात"</string>
     <string name="battery_info_status_charging" msgid="1705179948350365604">"चार्ज हो रही है"</string>
     <string name="battery_info_status_charging_lower" msgid="8689770213898117994">"चार्ज किया जा रहा है"</string>
diff --git a/packages/SettingsLib/res/values-hr/strings.xml b/packages/SettingsLib/res/values-hr/strings.xml
index 6d957dc..0fc16f8 100644
--- a/packages/SettingsLib/res/values-hr/strings.xml
+++ b/packages/SettingsLib/res/values-hr/strings.xml
@@ -402,8 +402,8 @@
     <string name="power_remaining_duration_shutdown_imminent" product="tablet" msgid="7466484148515796216">"Tablet bi se uskoro mogao isključiti (<xliff:g id="LEVEL">%1$s</xliff:g>)"</string>
     <string name="power_remaining_duration_shutdown_imminent" product="device" msgid="603933521600231649">"Uređaj bi se uskoro mogao isključiti (<xliff:g id="LEVEL">%1$s</xliff:g>)"</string>
     <string name="power_charging" msgid="1779532561355864267">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="STATE">%2$s</xliff:g>"</string>
-    <string name="power_remaining_charging_duration_only" msgid="1421102457410268886">"Još <xliff:g id="TIME">%1$s</xliff:g> do potpune napunjenosti"</string>
-    <string name="power_charging_duration" msgid="4676999980973411875">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g> do potpune napunjenosti"</string>
+    <string name="power_remaining_charging_duration_only" msgid="6672239353042034265">"Napunit će se za <xliff:g id="TIME">%1$s</xliff:g>"</string>
+    <string name="power_charging_duration" msgid="5850751284103249125">"<xliff:g id="LEVEL">%1$s</xliff:g> – napunit će se za <xliff:g id="TIME">%2$s</xliff:g>"</string>
     <string name="battery_info_status_unknown" msgid="196130600938058547">"Nepoznato"</string>
     <string name="battery_info_status_charging" msgid="1705179948350365604">"Punjenje"</string>
     <string name="battery_info_status_charging_lower" msgid="8689770213898117994">"punjenje"</string>
diff --git a/packages/SettingsLib/res/values-hu/strings.xml b/packages/SettingsLib/res/values-hu/strings.xml
index 39b5da2..45cd379 100644
--- a/packages/SettingsLib/res/values-hu/strings.xml
+++ b/packages/SettingsLib/res/values-hu/strings.xml
@@ -402,8 +402,8 @@
     <string name="power_remaining_duration_shutdown_imminent" product="tablet" msgid="7466484148515796216">"Előfordulhat, hogy a táblagép hamarosan leáll (<xliff:g id="LEVEL">%1$s</xliff:g>)"</string>
     <string name="power_remaining_duration_shutdown_imminent" product="device" msgid="603933521600231649">"Előfordulhat, hogy az eszköz hamarosan leáll (<xliff:g id="LEVEL">%1$s</xliff:g>)"</string>
     <string name="power_charging" msgid="1779532561355864267">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="STATE">%2$s</xliff:g>"</string>
-    <string name="power_remaining_charging_duration_only" msgid="1421102457410268886">"<xliff:g id="TIME">%1$s</xliff:g> a teljes töltöttségig"</string>
-    <string name="power_charging_duration" msgid="4676999980973411875">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> a teljes feltöltésig"</string>
+    <string name="power_remaining_charging_duration_only" msgid="6672239353042034265">"<xliff:g id="TIME">%1$s</xliff:g> van hátra a feltöltésig"</string>
+    <string name="power_charging_duration" msgid="5850751284103249125">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g> a feltöltésig"</string>
     <string name="battery_info_status_unknown" msgid="196130600938058547">"Ismeretlen"</string>
     <string name="battery_info_status_charging" msgid="1705179948350365604">"Töltés"</string>
     <string name="battery_info_status_charging_lower" msgid="8689770213898117994">"töltés"</string>
diff --git a/packages/SettingsLib/res/values-hy/strings.xml b/packages/SettingsLib/res/values-hy/strings.xml
index 16d7ea4..2145adb 100644
--- a/packages/SettingsLib/res/values-hy/strings.xml
+++ b/packages/SettingsLib/res/values-hy/strings.xml
@@ -402,8 +402,8 @@
     <string name="power_remaining_duration_shutdown_imminent" product="tablet" msgid="7466484148515796216">"Պլանշետը շուտով կանջատվի (<xliff:g id="LEVEL">%1$s</xliff:g>)"</string>
     <string name="power_remaining_duration_shutdown_imminent" product="device" msgid="603933521600231649">"Սարքը շուտով կանջատվի (<xliff:g id="LEVEL">%1$s</xliff:g>)"</string>
     <string name="power_charging" msgid="1779532561355864267">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string>
-    <string name="power_remaining_charging_duration_only" msgid="1421102457410268886">"Մինչև լրիվ լիցքավորումը մնացել է <xliff:g id="TIME">%1$s</xliff:g>"</string>
-    <string name="power_charging_duration" msgid="4676999980973411875">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g> մինչև լրիվ լիցքավորումը"</string>
+    <string name="power_remaining_charging_duration_only" msgid="6672239353042034265">"<xliff:g id="TIME">%1$s</xliff:g> մինչև լիցքավորումը"</string>
+    <string name="power_charging_duration" msgid="5850751284103249125">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g> մինչև լիցքավորումը"</string>
     <string name="battery_info_status_unknown" msgid="196130600938058547">"Անհայտ"</string>
     <string name="battery_info_status_charging" msgid="1705179948350365604">"Լիցքավորում"</string>
     <string name="battery_info_status_charging_lower" msgid="8689770213898117994">"լիցքավորում"</string>
diff --git a/packages/SettingsLib/res/values-in/strings.xml b/packages/SettingsLib/res/values-in/strings.xml
index 02c4c8c..15b6da5 100644
--- a/packages/SettingsLib/res/values-in/strings.xml
+++ b/packages/SettingsLib/res/values-in/strings.xml
@@ -402,8 +402,8 @@
     <string name="power_remaining_duration_shutdown_imminent" product="tablet" msgid="7466484148515796216">"Tablet mungkin segera dimatikan (<xliff:g id="LEVEL">%1$s</xliff:g>)"</string>
     <string name="power_remaining_duration_shutdown_imminent" product="device" msgid="603933521600231649">"Perangkat mungkin segera dimatikan (<xliff:g id="LEVEL">%1$s</xliff:g>)"</string>
     <string name="power_charging" msgid="1779532561355864267">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string>
-    <string name="power_remaining_charging_duration_only" msgid="1421102457410268886">"<xliff:g id="TIME">%1$s</xliff:g> lagi hingga terisi penuh"</string>
-    <string name="power_charging_duration" msgid="4676999980973411875">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> lagi terisi penuh"</string>
+    <string name="power_remaining_charging_duration_only" msgid="6672239353042034265">"Sisa <xliff:g id="TIME">%1$s</xliff:g> hingga terisi penuh"</string>
+    <string name="power_charging_duration" msgid="5850751284103249125">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> lagi terisi penuh"</string>
     <string name="battery_info_status_unknown" msgid="196130600938058547">"Tidak diketahui"</string>
     <string name="battery_info_status_charging" msgid="1705179948350365604">"Mengisi daya"</string>
     <string name="battery_info_status_charging_lower" msgid="8689770213898117994">"mengisi daya baterai"</string>
diff --git a/packages/SettingsLib/res/values-is/strings.xml b/packages/SettingsLib/res/values-is/strings.xml
index 11d69571..eede117 100644
--- a/packages/SettingsLib/res/values-is/strings.xml
+++ b/packages/SettingsLib/res/values-is/strings.xml
@@ -402,8 +402,8 @@
     <string name="power_remaining_duration_shutdown_imminent" product="tablet" msgid="7466484148515796216">"Spjaldtölvan gæti slökkt á sér fljótlega (<xliff:g id="LEVEL">%1$s</xliff:g>)"</string>
     <string name="power_remaining_duration_shutdown_imminent" product="device" msgid="603933521600231649">"Tækið gæti slökkt á sér fljótlega (<xliff:g id="LEVEL">%1$s</xliff:g>)"</string>
     <string name="power_charging" msgid="1779532561355864267">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="STATE">%2$s</xliff:g>"</string>
-    <string name="power_remaining_charging_duration_only" msgid="1421102457410268886">"<xliff:g id="TIME">%1$s</xliff:g> þar til hleðslu er lokið"</string>
-    <string name="power_charging_duration" msgid="4676999980973411875">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> þar til fullri hleðslu er náð"</string>
+    <string name="power_remaining_charging_duration_only" msgid="6672239353042034265">"<xliff:g id="TIME">%1$s</xliff:g> að fullri hleðslu"</string>
+    <string name="power_charging_duration" msgid="5850751284103249125">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> að fullri hleðslu"</string>
     <string name="battery_info_status_unknown" msgid="196130600938058547">"Óþekkt"</string>
     <string name="battery_info_status_charging" msgid="1705179948350365604">"Í hleðslu"</string>
     <string name="battery_info_status_charging_lower" msgid="8689770213898117994">"í hleðslu"</string>
diff --git a/packages/SettingsLib/res/values-it/strings.xml b/packages/SettingsLib/res/values-it/strings.xml
index a43e8d6..2c64ec2 100644
--- a/packages/SettingsLib/res/values-it/strings.xml
+++ b/packages/SettingsLib/res/values-it/strings.xml
@@ -402,8 +402,8 @@
     <string name="power_remaining_duration_shutdown_imminent" product="tablet" msgid="7466484148515796216">"Il tablet potrebbe spegnersi a breve (<xliff:g id="LEVEL">%1$s</xliff:g>)"</string>
     <string name="power_remaining_duration_shutdown_imminent" product="device" msgid="603933521600231649">"Il dispositivo potrebbe spegnersi a breve (<xliff:g id="LEVEL">%1$s</xliff:g>)"</string>
     <string name="power_charging" msgid="1779532561355864267">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string>
-    <string name="power_remaining_charging_duration_only" msgid="1421102457410268886">"Tempo rimanente alla carica completa: <xliff:g id="TIME">%1$s</xliff:g>"</string>
-    <string name="power_charging_duration" msgid="4676999980973411875">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> alla carica completa"</string>
+    <string name="power_remaining_charging_duration_only" msgid="6672239353042034265">"Tempo rimanente alla carica completa: <xliff:g id="TIME">%1$s</xliff:g>"</string>
+    <string name="power_charging_duration" msgid="5850751284103249125">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> alla carica completa"</string>
     <string name="battery_info_status_unknown" msgid="196130600938058547">"Sconosciuta"</string>
     <string name="battery_info_status_charging" msgid="1705179948350365604">"In carica"</string>
     <string name="battery_info_status_charging_lower" msgid="8689770213898117994">"in carica"</string>
diff --git a/packages/SettingsLib/res/values-iw/strings.xml b/packages/SettingsLib/res/values-iw/strings.xml
index a3e049c..30d6a4a 100644
--- a/packages/SettingsLib/res/values-iw/strings.xml
+++ b/packages/SettingsLib/res/values-iw/strings.xml
@@ -402,8 +402,8 @@
     <string name="power_remaining_duration_shutdown_imminent" product="tablet" msgid="7466484148515796216">"ייתכן שהטאבלט ייכבה בקרוב (<xliff:g id="LEVEL">%1$s</xliff:g>)"</string>
     <string name="power_remaining_duration_shutdown_imminent" product="device" msgid="603933521600231649">"ייתכן שהמכשיר ייכבה בקרוב (<xliff:g id="LEVEL">%1$s</xliff:g>)"</string>
     <string name="power_charging" msgid="1779532561355864267">"<xliff:g id="LEVEL">%1$s</xliff:g>‏ - <xliff:g id="STATE">%2$s</xliff:g>"</string>
-    <string name="power_remaining_charging_duration_only" msgid="1421102457410268886">"<xliff:g id="TIME">%1$s</xliff:g> עד לטעינה מלאה"</string>
-    <string name="power_charging_duration" msgid="4676999980973411875">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> עד לטעינה מלאה"</string>
+    <string name="power_remaining_charging_duration_only" msgid="6672239353042034265">"נשארו <xliff:g id="TIME">%1$s</xliff:g> עד הטעינה"</string>
+    <string name="power_charging_duration" msgid="5850751284103249125">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> עד הטעינה"</string>
     <string name="battery_info_status_unknown" msgid="196130600938058547">"לא ידוע"</string>
     <string name="battery_info_status_charging" msgid="1705179948350365604">"בטעינה"</string>
     <string name="battery_info_status_charging_lower" msgid="8689770213898117994">"בטעינה"</string>
diff --git a/packages/SettingsLib/res/values-ja/strings.xml b/packages/SettingsLib/res/values-ja/strings.xml
index 50543d8..6cb5514 100644
--- a/packages/SettingsLib/res/values-ja/strings.xml
+++ b/packages/SettingsLib/res/values-ja/strings.xml
@@ -402,8 +402,8 @@
     <string name="power_remaining_duration_shutdown_imminent" product="tablet" msgid="7466484148515796216">"タブレットの電源がもうすぐ切れます(<xliff:g id="LEVEL">%1$s</xliff:g>)"</string>
     <string name="power_remaining_duration_shutdown_imminent" product="device" msgid="603933521600231649">"デバイスの電源がもうすぐ切れます(<xliff:g id="LEVEL">%1$s</xliff:g>)"</string>
     <string name="power_charging" msgid="1779532561355864267">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string>
-    <string name="power_remaining_charging_duration_only" msgid="1421102457410268886">"フル充電まであと <xliff:g id="TIME">%1$s</xliff:g>"</string>
-    <string name="power_charging_duration" msgid="4676999980973411875">"<xliff:g id="LEVEL">%1$s</xliff:g> - フル充電まで <xliff:g id="TIME">%2$s</xliff:g>"</string>
+    <string name="power_remaining_charging_duration_only" msgid="6672239353042034265">"充電完了まであと <xliff:g id="TIME">%1$s</xliff:g>"</string>
+    <string name="power_charging_duration" msgid="5850751284103249125">"<xliff:g id="LEVEL">%1$s</xliff:g> - 充電完了まで <xliff:g id="TIME">%2$s</xliff:g>"</string>
     <string name="battery_info_status_unknown" msgid="196130600938058547">"不明"</string>
     <string name="battery_info_status_charging" msgid="1705179948350365604">"充電中"</string>
     <string name="battery_info_status_charging_lower" msgid="8689770213898117994">"充電しています"</string>
diff --git a/packages/SettingsLib/res/values-ka/strings.xml b/packages/SettingsLib/res/values-ka/strings.xml
index 8b9b6b6..4c78a38 100644
--- a/packages/SettingsLib/res/values-ka/strings.xml
+++ b/packages/SettingsLib/res/values-ka/strings.xml
@@ -402,8 +402,8 @@
     <string name="power_remaining_duration_shutdown_imminent" product="tablet" msgid="7466484148515796216">"ტაბლეტი შეიძლება მალე გაითიშოს (<xliff:g id="LEVEL">%1$s</xliff:g>)"</string>
     <string name="power_remaining_duration_shutdown_imminent" product="device" msgid="603933521600231649">"მოწყობილობა შეიძლება მალე გაითიშოს (<xliff:g id="LEVEL">%1$s</xliff:g>)"</string>
     <string name="power_charging" msgid="1779532561355864267">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string>
-    <string name="power_remaining_charging_duration_only" msgid="1421102457410268886">"სრულ დატენვამდე დარჩენილია <xliff:g id="TIME">%1$s</xliff:g>"</string>
-    <string name="power_charging_duration" msgid="4676999980973411875">"<xliff:g id="LEVEL">%1$s</xliff:g> — სრულ დატენვამდე დარჩა <xliff:g id="TIME">%2$s</xliff:g>"</string>
+    <string name="power_remaining_charging_duration_only" msgid="6672239353042034265">"დატენვამდე დარჩა <xliff:g id="TIME">%1$s</xliff:g>"</string>
+    <string name="power_charging_duration" msgid="5850751284103249125">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> დატენვამდე"</string>
     <string name="battery_info_status_unknown" msgid="196130600938058547">"უცნობი"</string>
     <string name="battery_info_status_charging" msgid="1705179948350365604">"იტენება"</string>
     <string name="battery_info_status_charging_lower" msgid="8689770213898117994">"იტენება"</string>
diff --git a/packages/SettingsLib/res/values-kk/strings.xml b/packages/SettingsLib/res/values-kk/strings.xml
index 246e3eb..ce08657 100644
--- a/packages/SettingsLib/res/values-kk/strings.xml
+++ b/packages/SettingsLib/res/values-kk/strings.xml
@@ -402,8 +402,8 @@
     <string name="power_remaining_duration_shutdown_imminent" product="tablet" msgid="7466484148515796216">"Планшет көп ұзамай өшуі мүмкін (<xliff:g id="LEVEL">%1$s</xliff:g>)"</string>
     <string name="power_remaining_duration_shutdown_imminent" product="device" msgid="603933521600231649">"Құрылғы көп ұзамай өшуі мүмкін (<xliff:g id="LEVEL">%1$s</xliff:g>)"</string>
     <string name="power_charging" msgid="1779532561355864267">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string>
-    <string name="power_remaining_charging_duration_only" msgid="1421102457410268886">"Толық зарядталуына <xliff:g id="TIME">%1$s</xliff:g> қалды"</string>
-    <string name="power_charging_duration" msgid="4676999980973411875">"<xliff:g id="LEVEL">%1$s</xliff:g> – толық зарядталғанға дейін <xliff:g id="TIME">%2$s</xliff:g>"</string>
+    <string name="power_remaining_charging_duration_only" msgid="6672239353042034265">"Зарядталғанға дейін <xliff:g id="TIME">%1$s</xliff:g> қалды"</string>
+    <string name="power_charging_duration" msgid="5850751284103249125">"<xliff:g id="LEVEL">%1$s</xliff:g> – зарядталғанға дейін <xliff:g id="TIME">%2$s</xliff:g>"</string>
     <string name="battery_info_status_unknown" msgid="196130600938058547">"Белгісіз"</string>
     <string name="battery_info_status_charging" msgid="1705179948350365604">"Зарядталуда"</string>
     <string name="battery_info_status_charging_lower" msgid="8689770213898117994">"зарядталуда"</string>
diff --git a/packages/SettingsLib/res/values-km/strings.xml b/packages/SettingsLib/res/values-km/strings.xml
index 36cf2d4..43c9282 100644
--- a/packages/SettingsLib/res/values-km/strings.xml
+++ b/packages/SettingsLib/res/values-km/strings.xml
@@ -402,8 +402,8 @@
     <string name="power_remaining_duration_shutdown_imminent" product="tablet" msgid="7466484148515796216">"ថេប្លេត​អាចនឹង​បិទក្នុង​ពេលបន្តិច​ទៀត (<xliff:g id="LEVEL">%1$s</xliff:g>)"</string>
     <string name="power_remaining_duration_shutdown_imminent" product="device" msgid="603933521600231649">"ឧបករណ៍​អាចនឹង​បិទក្នុង​ពេលបន្តិច​ទៀត (<xliff:g id="LEVEL">%1$s</xliff:g>)"</string>
     <string name="power_charging" msgid="1779532561355864267">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string>
-    <string name="power_remaining_charging_duration_only" msgid="1421102457410268886">"<xliff:g id="TIME">%1$s</xliff:g> ទៀតទើបសាកថ្មពេញ"</string>
-    <string name="power_charging_duration" msgid="4676999980973411875">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> ទៀតទើបសាកថ្មពេញ"</string>
+    <string name="power_remaining_charging_duration_only" msgid="6672239353042034265">"<xliff:g id="TIME">%1$s</xliff:g> ទៀតទើប​ត្រូវសាក"</string>
+    <string name="power_charging_duration" msgid="5850751284103249125">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> ទៀតទើប​ត្រូវសាក"</string>
     <string name="battery_info_status_unknown" msgid="196130600938058547">"មិន​ស្គាល់"</string>
     <string name="battery_info_status_charging" msgid="1705179948350365604">"កំពុងបញ្ចូល​ថ្ម"</string>
     <string name="battery_info_status_charging_lower" msgid="8689770213898117994">"កំពុង​សាក​ថ្ម"</string>
diff --git a/packages/SettingsLib/res/values-kn/strings.xml b/packages/SettingsLib/res/values-kn/strings.xml
index 97eed0f..3fe9855 100644
--- a/packages/SettingsLib/res/values-kn/strings.xml
+++ b/packages/SettingsLib/res/values-kn/strings.xml
@@ -402,8 +402,8 @@
     <string name="power_remaining_duration_shutdown_imminent" product="tablet" msgid="7466484148515796216">"ಟ್ಯಾಬ್ಲೆಟ್‌‌ ಶೀಘ್ರದಲ್ಲೇ ಶಟ್ ಡೌನ್ ಆಗಬಹುದು (<xliff:g id="LEVEL">%1$s</xliff:g>)"</string>
     <string name="power_remaining_duration_shutdown_imminent" product="device" msgid="603933521600231649">"ಸಾಧನವು ಶೀಘ್ರದಲ್ಲೇ ಶಟ್ ಡೌನ್ ಆಗಬಹುದು (<xliff:g id="LEVEL">%1$s</xliff:g>)"</string>
     <string name="power_charging" msgid="1779532561355864267">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string>
-    <string name="power_remaining_charging_duration_only" msgid="1421102457410268886">"ಸಂಪೂರ್ಣ ಚಾರ್ಜ್ ಆಗಲು <xliff:g id="TIME">%1$s</xliff:g>"</string>
-    <string name="power_charging_duration" msgid="4676999980973411875">"<xliff:g id="LEVEL">%1$s</xliff:g> - ಸಂಪೂರ್ಣ ಚಾರ್ಜ್ ಆಗಲು <xliff:g id="TIME">%2$s</xliff:g>"</string>
+    <string name="power_remaining_charging_duration_only" msgid="6672239353042034265">"ಚಾರ್ಜ್ ಆಗಲು <xliff:g id="TIME">%1$s</xliff:g> ಸಮಯ ಬಾಕಿ ಇದೆ"</string>
+    <string name="power_charging_duration" msgid="5850751284103249125">"<xliff:g id="LEVEL">%1$s</xliff:g> - ಚಾರ್ಜ್ ಆಗಲು <xliff:g id="TIME">%2$s</xliff:g> ಸಮಯ ಬೇಕು"</string>
     <string name="battery_info_status_unknown" msgid="196130600938058547">"ಅಪರಿಚಿತ"</string>
     <string name="battery_info_status_charging" msgid="1705179948350365604">"ಚಾರ್ಜ್ ಆಗುತ್ತಿದೆ"</string>
     <string name="battery_info_status_charging_lower" msgid="8689770213898117994">"ಚಾರ್ಜ್ ಆಗುತ್ತಿದೆ"</string>
diff --git a/packages/SettingsLib/res/values-ko/strings.xml b/packages/SettingsLib/res/values-ko/strings.xml
index 8f8bbc1..ac44c0d 100644
--- a/packages/SettingsLib/res/values-ko/strings.xml
+++ b/packages/SettingsLib/res/values-ko/strings.xml
@@ -402,8 +402,8 @@
     <string name="power_remaining_duration_shutdown_imminent" product="tablet" msgid="7466484148515796216">"태블릿이 곧 종료될 수 있음(<xliff:g id="LEVEL">%1$s</xliff:g>)"</string>
     <string name="power_remaining_duration_shutdown_imminent" product="device" msgid="603933521600231649">"기기가 곧 종료될 수 있음(<xliff:g id="LEVEL">%1$s</xliff:g>)"</string>
     <string name="power_charging" msgid="1779532561355864267">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string>
-    <string name="power_remaining_charging_duration_only" msgid="1421102457410268886">"충전 완료까지 <xliff:g id="TIME">%1$s</xliff:g> 남음"</string>
-    <string name="power_charging_duration" msgid="4676999980973411875">"<xliff:g id="LEVEL">%1$s</xliff:g> - 충전 완료까지 <xliff:g id="TIME">%2$s</xliff:g> 남음"</string>
+    <string name="power_remaining_charging_duration_only" msgid="6672239353042034265">"충전 완료까지 <xliff:g id="TIME">%1$s</xliff:g> 남음"</string>
+    <string name="power_charging_duration" msgid="5850751284103249125">"<xliff:g id="LEVEL">%1$s</xliff:g> - 충전 완료까지 <xliff:g id="TIME">%2$s</xliff:g> 남음"</string>
     <string name="battery_info_status_unknown" msgid="196130600938058547">"알 수 없음"</string>
     <string name="battery_info_status_charging" msgid="1705179948350365604">"충전 중"</string>
     <string name="battery_info_status_charging_lower" msgid="8689770213898117994">"충전 중"</string>
diff --git a/packages/SettingsLib/res/values-ky/strings.xml b/packages/SettingsLib/res/values-ky/strings.xml
index 435ce53..72b2159 100644
--- a/packages/SettingsLib/res/values-ky/strings.xml
+++ b/packages/SettingsLib/res/values-ky/strings.xml
@@ -402,8 +402,8 @@
     <string name="power_remaining_duration_shutdown_imminent" product="tablet" msgid="7466484148515796216">"Планшет бир аздан кийин өчүп калышы мүмкүн (<xliff:g id="LEVEL">%1$s</xliff:g>)"</string>
     <string name="power_remaining_duration_shutdown_imminent" product="device" msgid="603933521600231649">"Түзмөк бир аздан кийин өчүп калышы мүмкүн (<xliff:g id="LEVEL">%1$s</xliff:g>)"</string>
     <string name="power_charging" msgid="1779532561355864267">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string>
-    <string name="power_remaining_charging_duration_only" msgid="1421102457410268886">"Батарея толгонго чейин калган убакыт: <xliff:g id="TIME">%1$s</xliff:g>"</string>
-    <string name="power_charging_duration" msgid="4676999980973411875">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g> кийин толук кубатталат"</string>
+    <string name="power_remaining_charging_duration_only" msgid="6672239353042034265">"<xliff:g id="TIME">%1$s</xliff:g> кийин кубатталат"</string>
+    <string name="power_charging_duration" msgid="5850751284103249125">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> кийин кубатталат"</string>
     <string name="battery_info_status_unknown" msgid="196130600938058547">"Белгисиз"</string>
     <string name="battery_info_status_charging" msgid="1705179948350365604">"Кубатталууда"</string>
     <string name="battery_info_status_charging_lower" msgid="8689770213898117994">"кубатталууда"</string>
diff --git a/packages/SettingsLib/res/values-lo/strings.xml b/packages/SettingsLib/res/values-lo/strings.xml
index 1cee8fb..28e8111 100644
--- a/packages/SettingsLib/res/values-lo/strings.xml
+++ b/packages/SettingsLib/res/values-lo/strings.xml
@@ -402,8 +402,8 @@
     <string name="power_remaining_duration_shutdown_imminent" product="tablet" msgid="7466484148515796216">"ແທັບເລັດອາດຈະປິດໃນໄວໆນີ້ (<xliff:g id="LEVEL">%1$s</xliff:g>)"</string>
     <string name="power_remaining_duration_shutdown_imminent" product="device" msgid="603933521600231649">"ອຸປະກອນອາດຈະປິດໃນໄວໆນີ້ (<xliff:g id="LEVEL">%1$s</xliff:g>)"</string>
     <string name="power_charging" msgid="1779532561355864267">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string>
-    <string name="power_remaining_charging_duration_only" msgid="1421102457410268886">"<xliff:g id="TIME">%1$s</xliff:g> ຈົນກວ່າຈະສາກເຕັມ"</string>
-    <string name="power_charging_duration" msgid="4676999980973411875">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> ຈົນກວ່າຈະສາກເຕັມ"</string>
+    <string name="power_remaining_charging_duration_only" msgid="6672239353042034265">"<xliff:g id="TIME">%1$s</xliff:g> ຈົນກວ່າຈະສາກເຕັມ"</string>
+    <string name="power_charging_duration" msgid="5850751284103249125">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> ຈົນກວ່າຈະສາກເຕັມ"</string>
     <string name="battery_info_status_unknown" msgid="196130600938058547">"ບໍ່ຮູ້ຈັກ"</string>
     <string name="battery_info_status_charging" msgid="1705179948350365604">"ກຳລັງສາກໄຟ"</string>
     <string name="battery_info_status_charging_lower" msgid="8689770213898117994">"ກຳລັງສາກໄຟ"</string>
diff --git a/packages/SettingsLib/res/values-lt/strings.xml b/packages/SettingsLib/res/values-lt/strings.xml
index c10bd00..93fcaa7 100644
--- a/packages/SettingsLib/res/values-lt/strings.xml
+++ b/packages/SettingsLib/res/values-lt/strings.xml
@@ -402,8 +402,8 @@
     <string name="power_remaining_duration_shutdown_imminent" product="tablet" msgid="7466484148515796216">"Planšetinis kompiuteris netrukus gali būti išjungtas (<xliff:g id="LEVEL">%1$s</xliff:g>)"</string>
     <string name="power_remaining_duration_shutdown_imminent" product="device" msgid="603933521600231649">"Įrenginys netrukus gali būti išjungtas (<xliff:g id="LEVEL">%1$s</xliff:g>)"</string>
     <string name="power_charging" msgid="1779532561355864267">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="STATE">%2$s</xliff:g>"</string>
-    <string name="power_remaining_charging_duration_only" msgid="1421102457410268886">"Iki visiškos įkrovos liko <xliff:g id="TIME">%1$s</xliff:g>"</string>
-    <string name="power_charging_duration" msgid="4676999980973411875">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g> iki visiško įkrovimo"</string>
+    <string name="power_remaining_charging_duration_only" msgid="6672239353042034265">"Iki visiškos įkrovos liko <xliff:g id="TIME">%1$s</xliff:g>"</string>
+    <string name="power_charging_duration" msgid="5850751284103249125">"<xliff:g id="LEVEL">%1$s</xliff:g> – iki visiškos įkrovos liko <xliff:g id="TIME">%2$s</xliff:g>"</string>
     <string name="battery_info_status_unknown" msgid="196130600938058547">"Nežinomas"</string>
     <string name="battery_info_status_charging" msgid="1705179948350365604">"Kraunasi..."</string>
     <string name="battery_info_status_charging_lower" msgid="8689770213898117994">"įkraunama"</string>
diff --git a/packages/SettingsLib/res/values-lv/strings.xml b/packages/SettingsLib/res/values-lv/strings.xml
index 96aebc5..c12d097 100644
--- a/packages/SettingsLib/res/values-lv/strings.xml
+++ b/packages/SettingsLib/res/values-lv/strings.xml
@@ -402,8 +402,8 @@
     <string name="power_remaining_duration_shutdown_imminent" product="tablet" msgid="7466484148515796216">"Iespējams, planšetdators drīz izslēgsies (<xliff:g id="LEVEL">%1$s</xliff:g>)"</string>
     <string name="power_remaining_duration_shutdown_imminent" product="device" msgid="603933521600231649">"Iespējams, ierīce drīz izslēgsies (<xliff:g id="LEVEL">%1$s</xliff:g>)"</string>
     <string name="power_charging" msgid="1779532561355864267">"<xliff:g id="LEVEL">%1$s</xliff:g> — <xliff:g id="STATE">%2$s</xliff:g>"</string>
-    <string name="power_remaining_charging_duration_only" msgid="1421102457410268886">"Atlikušais laiks līdz pilnai uzlādei: <xliff:g id="TIME">%1$s</xliff:g>"</string>
-    <string name="power_charging_duration" msgid="4676999980973411875">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> līdz pilnīgai uzlādei"</string>
+    <string name="power_remaining_charging_duration_only" msgid="6672239353042034265">"Vēl <xliff:g id="TIME">%1$s</xliff:g> līdz pilnai uzlādei"</string>
+    <string name="power_charging_duration" msgid="5850751284103249125">"<xliff:g id="LEVEL">%1$s</xliff:g> — <xliff:g id="TIME">%2$s</xliff:g> līdz pilnai uzlādei"</string>
     <string name="battery_info_status_unknown" msgid="196130600938058547">"Nezināms"</string>
     <string name="battery_info_status_charging" msgid="1705179948350365604">"Uzlāde"</string>
     <string name="battery_info_status_charging_lower" msgid="8689770213898117994">"notiek uzlāde"</string>
diff --git a/packages/SettingsLib/res/values-mk/strings.xml b/packages/SettingsLib/res/values-mk/strings.xml
index d93304f..9a76a0a 100644
--- a/packages/SettingsLib/res/values-mk/strings.xml
+++ b/packages/SettingsLib/res/values-mk/strings.xml
@@ -402,8 +402,8 @@
     <string name="power_remaining_duration_shutdown_imminent" product="tablet" msgid="7466484148515796216">"Таблетот може да се исклучи наскоро (<xliff:g id="LEVEL">%1$s</xliff:g>)"</string>
     <string name="power_remaining_duration_shutdown_imminent" product="device" msgid="603933521600231649">"Уредот може да се исклучи наскоро (<xliff:g id="LEVEL">%1$s</xliff:g>)"</string>
     <string name="power_charging" msgid="1779532561355864267">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="STATE">%2$s</xliff:g>"</string>
-    <string name="power_remaining_charging_duration_only" msgid="1421102457410268886">"Преостануваат <xliff:g id="TIME">%1$s</xliff:g> дури се наполни целосно"</string>
-    <string name="power_charging_duration" msgid="4676999980973411875">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> дури се наполни целосно"</string>
+    <string name="power_remaining_charging_duration_only" msgid="6672239353042034265">"Уште <xliff:g id="TIME">%1$s</xliff:g> до целосно полнење"</string>
+    <string name="power_charging_duration" msgid="5850751284103249125">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> до целосно полнење"</string>
     <string name="battery_info_status_unknown" msgid="196130600938058547">"Непознато"</string>
     <string name="battery_info_status_charging" msgid="1705179948350365604">"Се полни"</string>
     <string name="battery_info_status_charging_lower" msgid="8689770213898117994">"се полни"</string>
diff --git a/packages/SettingsLib/res/values-ml/strings.xml b/packages/SettingsLib/res/values-ml/strings.xml
index 7016b7f..bb76295 100644
--- a/packages/SettingsLib/res/values-ml/strings.xml
+++ b/packages/SettingsLib/res/values-ml/strings.xml
@@ -402,8 +402,8 @@
     <string name="power_remaining_duration_shutdown_imminent" product="tablet" msgid="7466484148515796216">"ടാബ്‌ലെറ്റ് ഉടൻ ഷട്ട് ഡൗൺ ആയേക്കാം (<xliff:g id="LEVEL">%1$s</xliff:g>)"</string>
     <string name="power_remaining_duration_shutdown_imminent" product="device" msgid="603933521600231649">"ഉപകരണം ഉടൻ ഷട്ട്ഡൗൺ ആയേക്കാം (<xliff:g id="LEVEL">%1$s</xliff:g>)"</string>
     <string name="power_charging" msgid="1779532561355864267">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string>
-    <string name="power_remaining_charging_duration_only" msgid="1421102457410268886">"മുഴുവൻ ചാർജാകാൻ <xliff:g id="TIME">%1$s</xliff:g> ശേഷിക്കുന്നു"</string>
-    <string name="power_charging_duration" msgid="4676999980973411875">"<xliff:g id="LEVEL">%1$s</xliff:g> - ഫുൾ ചാർജാകാൻ <xliff:g id="TIME">%2$s</xliff:g>"</string>
+    <string name="power_remaining_charging_duration_only" msgid="6672239353042034265">"പൂർണ്ണമായി ചാർജാവാൻ <xliff:g id="TIME">%1$s</xliff:g> ശേഷിക്കുന്നു"</string>
+    <string name="power_charging_duration" msgid="5850751284103249125">"<xliff:g id="LEVEL">%1$s</xliff:g> - പൂർണ്ണമായി ചാർജാവാൻ <xliff:g id="TIME">%2$s</xliff:g>"</string>
     <string name="battery_info_status_unknown" msgid="196130600938058547">"അജ്ഞാതം"</string>
     <string name="battery_info_status_charging" msgid="1705179948350365604">"ചാർജ് ചെയ്യുന്നു"</string>
     <string name="battery_info_status_charging_lower" msgid="8689770213898117994">"ചാർജ് ചെയ്യുന്നു"</string>
diff --git a/packages/SettingsLib/res/values-mn/strings.xml b/packages/SettingsLib/res/values-mn/strings.xml
index 80e78a3..65a8ca6 100644
--- a/packages/SettingsLib/res/values-mn/strings.xml
+++ b/packages/SettingsLib/res/values-mn/strings.xml
@@ -402,8 +402,8 @@
     <string name="power_remaining_duration_shutdown_imminent" product="tablet" msgid="7466484148515796216">"Таблет удахгүй унтарна (<xliff:g id="LEVEL">%1$s</xliff:g>)"</string>
     <string name="power_remaining_duration_shutdown_imminent" product="device" msgid="603933521600231649">"Төхөөрөмж удахгүй унтарна (<xliff:g id="LEVEL">%1$s</xliff:g>)"</string>
     <string name="power_charging" msgid="1779532561355864267">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string>
-    <string name="power_remaining_charging_duration_only" msgid="1421102457410268886">"Бүрэн цэнэглэх хүртэл <xliff:g id="TIME">%1$s</xliff:g> үлдсэн"</string>
-    <string name="power_charging_duration" msgid="4676999980973411875">"бүрэн цэнэглэх хүртэл <xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g>"</string>
+    <string name="power_remaining_charging_duration_only" msgid="6672239353042034265">"Цэнэглэх хүртэл үлдсэн <xliff:g id="TIME">%1$s</xliff:g>"</string>
+    <string name="power_charging_duration" msgid="5850751284103249125">"<xliff:g id="LEVEL">%1$s</xliff:g> - цэнэглэх хүртэл <xliff:g id="TIME">%2$s</xliff:g>"</string>
     <string name="battery_info_status_unknown" msgid="196130600938058547">"Тодорхойгүй"</string>
     <string name="battery_info_status_charging" msgid="1705179948350365604">"Цэнэглэж байна"</string>
     <string name="battery_info_status_charging_lower" msgid="8689770213898117994">"цэнэглэж байна"</string>
diff --git a/packages/SettingsLib/res/values-mr/strings.xml b/packages/SettingsLib/res/values-mr/strings.xml
index 54723a8..3d75ad6 100644
--- a/packages/SettingsLib/res/values-mr/strings.xml
+++ b/packages/SettingsLib/res/values-mr/strings.xml
@@ -402,8 +402,8 @@
     <string name="power_remaining_duration_shutdown_imminent" product="tablet" msgid="7466484148515796216">"टॅबलेट लवकरच बंद होऊ शकतो (<xliff:g id="LEVEL">%1$s</xliff:g>)"</string>
     <string name="power_remaining_duration_shutdown_imminent" product="device" msgid="603933521600231649">"डिव्हाइस लवकरच बंद पडू शकते (<xliff:g id="LEVEL">%1$s</xliff:g>)"</string>
     <string name="power_charging" msgid="1779532561355864267">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string>
-    <string name="power_remaining_charging_duration_only" msgid="1421102457410268886">"पूर्णपणे चार्ज होण्यास <xliff:g id="TIME">%1$s</xliff:g> शिल्‍लक"</string>
-    <string name="power_charging_duration" msgid="4676999980973411875">"<xliff:g id="LEVEL">%1$s</xliff:g> - पूर्णपणे चार्ज होण्यात <xliff:g id="TIME">%2$s</xliff:g>"</string>
+    <string name="power_remaining_charging_duration_only" msgid="6672239353042034265">"<xliff:g id="TIME">%1$s</xliff:g> पर्यंत पूर्ण चार्ज होईल"</string>
+    <string name="power_charging_duration" msgid="5850751284103249125">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> पर्यंत पूर्ण चार्ज होईल"</string>
     <string name="battery_info_status_unknown" msgid="196130600938058547">"अज्ञात"</string>
     <string name="battery_info_status_charging" msgid="1705179948350365604">"चार्ज होत आहे"</string>
     <string name="battery_info_status_charging_lower" msgid="8689770213898117994">"चार्ज होत आहे"</string>
diff --git a/packages/SettingsLib/res/values-ms/strings.xml b/packages/SettingsLib/res/values-ms/strings.xml
index 3841a3b..0b2a4b0 100644
--- a/packages/SettingsLib/res/values-ms/strings.xml
+++ b/packages/SettingsLib/res/values-ms/strings.xml
@@ -402,8 +402,8 @@
     <string name="power_remaining_duration_shutdown_imminent" product="tablet" msgid="7466484148515796216">"Tablet mungkin ditutup tidak lama lagi (<xliff:g id="LEVEL">%1$s</xliff:g>)"</string>
     <string name="power_remaining_duration_shutdown_imminent" product="device" msgid="603933521600231649">"Peranti mungkin ditutup tidak lama lagi (<xliff:g id="LEVEL">%1$s</xliff:g>)"</string>
     <string name="power_charging" msgid="1779532561355864267">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string>
-    <string name="power_remaining_charging_duration_only" msgid="1421102457410268886">"<xliff:g id="TIME">%1$s</xliff:g> lagi sehingga dicas penuh"</string>
-    <string name="power_charging_duration" msgid="4676999980973411875">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> sehingga dicas penuh"</string>
+    <string name="power_remaining_charging_duration_only" msgid="6672239353042034265">"<xliff:g id="TIME">%1$s</xliff:g> lagi sehingga dicas penuh"</string>
+    <string name="power_charging_duration" msgid="5850751284103249125">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> sehingga dicas"</string>
     <string name="battery_info_status_unknown" msgid="196130600938058547">"Tidak diketahui"</string>
     <string name="battery_info_status_charging" msgid="1705179948350365604">"Mengecas"</string>
     <string name="battery_info_status_charging_lower" msgid="8689770213898117994">"mengecas"</string>
diff --git a/packages/SettingsLib/res/values-my/strings.xml b/packages/SettingsLib/res/values-my/strings.xml
index 38f128a..6fde69a 100644
--- a/packages/SettingsLib/res/values-my/strings.xml
+++ b/packages/SettingsLib/res/values-my/strings.xml
@@ -402,8 +402,8 @@
     <string name="power_remaining_duration_shutdown_imminent" product="tablet" msgid="7466484148515796216">"မကြာမီ တက်ဘလက် ပိတ်သွားနိုင်သည် (<xliff:g id="LEVEL">%1$s</xliff:g>)"</string>
     <string name="power_remaining_duration_shutdown_imminent" product="device" msgid="603933521600231649">"မကြာမီ စက်ပိတ်သွားနိုင်သည် (<xliff:g id="LEVEL">%1$s</xliff:g>)"</string>
     <string name="power_charging" msgid="1779532561355864267">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string>
-    <string name="power_remaining_charging_duration_only" msgid="1421102457410268886">"အားပြည့်ရန် <xliff:g id="TIME">%1$s</xliff:g> လိုပါသည်"</string>
-    <string name="power_charging_duration" msgid="4676999980973411875">"<xliff:g id="LEVEL">%1$s</xliff:g> − အားပြည့်ရန် <xliff:g id="TIME">%2$s</xliff:g> ကျန်သည်"</string>
+    <string name="power_remaining_charging_duration_only" msgid="6672239353042034265">"အားပြည့်ရန် <xliff:g id="TIME">%1$s</xliff:g> ကျန်သည်"</string>
+    <string name="power_charging_duration" msgid="5850751284103249125">"<xliff:g id="LEVEL">%1$s</xliff:g> - အားပြည့်ရန် <xliff:g id="TIME">%2$s</xliff:g> ကျန်သည်"</string>
     <string name="battery_info_status_unknown" msgid="196130600938058547">"မသိ"</string>
     <string name="battery_info_status_charging" msgid="1705179948350365604">"အားသွင်းနေပါသည်"</string>
     <string name="battery_info_status_charging_lower" msgid="8689770213898117994">"အားသွင်းနေပါသည်"</string>
diff --git a/packages/SettingsLib/res/values-nb/strings.xml b/packages/SettingsLib/res/values-nb/strings.xml
index 144d4c2..66ad20e 100644
--- a/packages/SettingsLib/res/values-nb/strings.xml
+++ b/packages/SettingsLib/res/values-nb/strings.xml
@@ -402,8 +402,8 @@
     <string name="power_remaining_duration_shutdown_imminent" product="tablet" msgid="7466484148515796216">"Nettbrettet slås kanskje av snart (<xliff:g id="LEVEL">%1$s</xliff:g>)"</string>
     <string name="power_remaining_duration_shutdown_imminent" product="device" msgid="603933521600231649">"Enheten slås kanskje av snart (<xliff:g id="LEVEL">%1$s</xliff:g>)"</string>
     <string name="power_charging" msgid="1779532561355864267">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="STATE">%2$s</xliff:g>"</string>
-    <string name="power_remaining_charging_duration_only" msgid="1421102457410268886">"<xliff:g id="TIME">%1$s</xliff:g> til det er fulladet"</string>
-    <string name="power_charging_duration" msgid="4676999980973411875">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g> til det er fulladet"</string>
+    <string name="power_remaining_charging_duration_only" msgid="6672239353042034265">"<xliff:g id="TIME">%1$s</xliff:g> til batteriet er fulladet"</string>
+    <string name="power_charging_duration" msgid="5850751284103249125">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g> til batteriet er fulladet"</string>
     <string name="battery_info_status_unknown" msgid="196130600938058547">"Ukjent"</string>
     <string name="battery_info_status_charging" msgid="1705179948350365604">"Lader"</string>
     <string name="battery_info_status_charging_lower" msgid="8689770213898117994">"lader"</string>
diff --git a/packages/SettingsLib/res/values-ne/strings.xml b/packages/SettingsLib/res/values-ne/strings.xml
index b2e1cd6..860e9bf 100644
--- a/packages/SettingsLib/res/values-ne/strings.xml
+++ b/packages/SettingsLib/res/values-ne/strings.xml
@@ -402,8 +402,8 @@
     <string name="power_remaining_duration_shutdown_imminent" product="tablet" msgid="7466484148515796216">"ट्याब्लेट चाँडै बन्द हुन सक्छ (<xliff:g id="LEVEL">%1$s</xliff:g>)"</string>
     <string name="power_remaining_duration_shutdown_imminent" product="device" msgid="603933521600231649">"यन्त्र चाँडै बन्द हुन सक्छ (<xliff:g id="LEVEL">%1$s</xliff:g>)"</string>
     <string name="power_charging" msgid="1779532561355864267">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string>
-    <string name="power_remaining_charging_duration_only" msgid="1421102457410268886">"पूर्णरूपमा चार्ज हुन <xliff:g id="TIME">%1$s</xliff:g> बाँकी"</string>
-    <string name="power_charging_duration" msgid="4676999980973411875">"<xliff:g id="LEVEL">%1$s</xliff:g> - पूर्णरूपमा चार्ज हुन <xliff:g id="TIME">%2$s</xliff:g> बाँकी"</string>
+    <string name="power_remaining_charging_duration_only" msgid="6672239353042034265">"पूर्ण चार्ज हुन <xliff:g id="TIME">%1$s</xliff:g> बाँकी"</string>
+    <string name="power_charging_duration" msgid="5850751284103249125">"पूर्ण चार्ज हुन <xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> लाग्छ"</string>
     <string name="battery_info_status_unknown" msgid="196130600938058547">"अज्ञात"</string>
     <string name="battery_info_status_charging" msgid="1705179948350365604">"चार्ज हुँदै"</string>
     <string name="battery_info_status_charging_lower" msgid="8689770213898117994">"चार्ज हुँदै"</string>
diff --git a/packages/SettingsLib/res/values-nl/strings.xml b/packages/SettingsLib/res/values-nl/strings.xml
index c50b43a..2fff3283 100644
--- a/packages/SettingsLib/res/values-nl/strings.xml
+++ b/packages/SettingsLib/res/values-nl/strings.xml
@@ -402,8 +402,8 @@
     <string name="power_remaining_duration_shutdown_imminent" product="tablet" msgid="7466484148515796216">"Tablet wordt binnenkort mogelijk uitgeschakeld (<xliff:g id="LEVEL">%1$s</xliff:g>)"</string>
     <string name="power_remaining_duration_shutdown_imminent" product="device" msgid="603933521600231649">"Apparaat wordt binnenkort mogelijk uitgeschakeld (<xliff:g id="LEVEL">%1$s</xliff:g>)"</string>
     <string name="power_charging" msgid="1779532561355864267">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string>
-    <string name="power_remaining_charging_duration_only" msgid="1421102457410268886">"Nog <xliff:g id="TIME">%1$s</xliff:g> tot volledig opgeladen"</string>
-    <string name="power_charging_duration" msgid="4676999980973411875">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> tot volledig opgeladen"</string>
+    <string name="power_remaining_charging_duration_only" msgid="6672239353042034265">"Nog <xliff:g id="TIME">%1$s</xliff:g> tot opgeladen"</string>
+    <string name="power_charging_duration" msgid="5850751284103249125">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> tot opgeladen"</string>
     <string name="battery_info_status_unknown" msgid="196130600938058547">"Onbekend"</string>
     <string name="battery_info_status_charging" msgid="1705179948350365604">"Opladen"</string>
     <string name="battery_info_status_charging_lower" msgid="8689770213898117994">"opladen"</string>
diff --git a/packages/SettingsLib/res/values-or/strings.xml b/packages/SettingsLib/res/values-or/strings.xml
index f9e0d39..ff2a534 100644
--- a/packages/SettingsLib/res/values-or/strings.xml
+++ b/packages/SettingsLib/res/values-or/strings.xml
@@ -402,8 +402,8 @@
     <string name="power_remaining_duration_shutdown_imminent" product="tablet" msgid="7466484148515796216">"ଖୁବ୍ ଶୀଘ୍ର ଟାବଲେଟ୍‌ଟି ବନ୍ଦ ହୋଇଯାଇପାରେ (<xliff:g id="LEVEL">%1$s</xliff:g>)"</string>
     <string name="power_remaining_duration_shutdown_imminent" product="device" msgid="603933521600231649">"ଖୁବ୍ ଶୀଘ୍ର ଡିଭାଇସ୍‌ଟି ବନ୍ଦ ହୋଇଯାଇପାରେ(<xliff:g id="LEVEL">%1$s</xliff:g>)"</string>
     <string name="power_charging" msgid="1779532561355864267">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string>
-    <string name="power_remaining_charging_duration_only" msgid="1421102457410268886">"ସମ୍ପୂର୍ଣ୍ଣ ଚାର୍ଜ ହେବାପାଇଁ <xliff:g id="TIME">%1$s</xliff:g> ବାକି ଅଛି"</string>
-    <string name="power_charging_duration" msgid="4676999980973411875">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> ପୂର୍ଣ୍ଣ ଚାର୍ଜ ହେବା ପର୍ଯ୍ୟନ୍ତ"</string>
+    <string name="power_remaining_charging_duration_only" msgid="6672239353042034265">"ଚାର୍ଜ ହେବା ପାଇଁ <xliff:g id="TIME">%1$s</xliff:g> ବାକି ଅଛି"</string>
+    <string name="power_charging_duration" msgid="5850751284103249125">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> ଚାର୍ଜ ହେବା ପର୍ଯ୍ୟନ୍ତ"</string>
     <string name="battery_info_status_unknown" msgid="196130600938058547">"ଅଜ୍ଞାତ"</string>
     <string name="battery_info_status_charging" msgid="1705179948350365604">"ଚାର୍ଜ ହେଉଛି"</string>
     <string name="battery_info_status_charging_lower" msgid="8689770213898117994">"ଚାର୍ଜ ହେଉଛି"</string>
diff --git a/packages/SettingsLib/res/values-pa/strings.xml b/packages/SettingsLib/res/values-pa/strings.xml
index b5acd8e..0cf95753 100644
--- a/packages/SettingsLib/res/values-pa/strings.xml
+++ b/packages/SettingsLib/res/values-pa/strings.xml
@@ -402,8 +402,8 @@
     <string name="power_remaining_duration_shutdown_imminent" product="tablet" msgid="7466484148515796216">"ਟੈਬਲੈੱਟ ਛੇਤੀ ਹੀ ਬੰਦ ਹੋ ਸਕਦਾ ਹੈ (<xliff:g id="LEVEL">%1$s</xliff:g>)"</string>
     <string name="power_remaining_duration_shutdown_imminent" product="device" msgid="603933521600231649">"ਡੀਵਾਈਸ ਛੇਤੀ ਹੀ ਬੰਦ ਹੋ ਸਕਦਾ ਹੈ (<xliff:g id="LEVEL">%1$s</xliff:g>)"</string>
     <string name="power_charging" msgid="1779532561355864267">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string>
-    <string name="power_remaining_charging_duration_only" msgid="1421102457410268886">"ਪੂਰੀ ਤਰ੍ਹਾਂ ਚਾਰਜ ਹੋਣ ਲਈ <xliff:g id="TIME">%1$s</xliff:g> ਬਾਕੀ"</string>
-    <string name="power_charging_duration" msgid="4676999980973411875">"<xliff:g id="LEVEL">%1$s</xliff:g> - ਪੂਰੀ ਤਰ੍ਹਾਂ ਚਾਰਜ ਹੋਣ ਵਿੱਚ <xliff:g id="TIME">%2$s</xliff:g>"</string>
+    <string name="power_remaining_charging_duration_only" msgid="6672239353042034265">"ਚਾਰਜ ਹੋਣ ਵਿੱਚ <xliff:g id="TIME">%1$s</xliff:g> ਬਾਕੀ"</string>
+    <string name="power_charging_duration" msgid="5850751284103249125">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> ਤੱਕ ਚਾਰਜ ਹੋ ਜਾਵੇਗੀ"</string>
     <string name="battery_info_status_unknown" msgid="196130600938058547">"ਅਗਿਆਤ"</string>
     <string name="battery_info_status_charging" msgid="1705179948350365604">"ਚਾਰਜ ਹੋ ਰਿਹਾ ਹੈ"</string>
     <string name="battery_info_status_charging_lower" msgid="8689770213898117994">"ਚਾਰਜ ਕੀਤਾ ਜਾ ਰਿਹਾ ਹੈ"</string>
diff --git a/packages/SettingsLib/res/values-pl/strings.xml b/packages/SettingsLib/res/values-pl/strings.xml
index 60a4c53..caed8c3 100644
--- a/packages/SettingsLib/res/values-pl/strings.xml
+++ b/packages/SettingsLib/res/values-pl/strings.xml
@@ -402,8 +402,8 @@
     <string name="power_remaining_duration_shutdown_imminent" product="tablet" msgid="7466484148515796216">"Tablet może się wkrótce wyłączyć (<xliff:g id="LEVEL">%1$s</xliff:g>)"</string>
     <string name="power_remaining_duration_shutdown_imminent" product="device" msgid="603933521600231649">"Urządzenie może się wkrótce wyłączyć (<xliff:g id="LEVEL">%1$s</xliff:g>)"</string>
     <string name="power_charging" msgid="1779532561355864267">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="STATE">%2$s</xliff:g>"</string>
-    <string name="power_remaining_charging_duration_only" msgid="1421102457410268886">"<xliff:g id="TIME">%1$s</xliff:g> do pełnego naładowania"</string>
-    <string name="power_charging_duration" msgid="4676999980973411875">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g> do pełnego naładowania"</string>
+    <string name="power_remaining_charging_duration_only" msgid="6672239353042034265">"Do naładowania <xliff:g id="TIME">%1$s</xliff:g>"</string>
+    <string name="power_charging_duration" msgid="5850751284103249125">"<xliff:g id="LEVEL">%1$s</xliff:g> – do naładowania <xliff:g id="TIME">%2$s</xliff:g>"</string>
     <string name="battery_info_status_unknown" msgid="196130600938058547">"Nieznane"</string>
     <string name="battery_info_status_charging" msgid="1705179948350365604">"Ładowanie"</string>
     <string name="battery_info_status_charging_lower" msgid="8689770213898117994">"ładowanie"</string>
diff --git a/packages/SettingsLib/res/values-pt-rBR/strings.xml b/packages/SettingsLib/res/values-pt-rBR/strings.xml
index dd0a75b..04a24f1 100644
--- a/packages/SettingsLib/res/values-pt-rBR/strings.xml
+++ b/packages/SettingsLib/res/values-pt-rBR/strings.xml
@@ -402,8 +402,8 @@
     <string name="power_remaining_duration_shutdown_imminent" product="tablet" msgid="7466484148515796216">"O tablet pode ser desligado em breve (<xliff:g id="LEVEL">%1$s</xliff:g>)"</string>
     <string name="power_remaining_duration_shutdown_imminent" product="device" msgid="603933521600231649">"O dispositivo pode ser desligado em breve (<xliff:g id="LEVEL">%1$s</xliff:g>)"</string>
     <string name="power_charging" msgid="1779532561355864267">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string>
-    <string name="power_remaining_charging_duration_only" msgid="1421102457410268886">"<xliff:g id="TIME">%1$s</xliff:g> restante(s) até a carga completa"</string>
-    <string name="power_charging_duration" msgid="4676999980973411875">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> até a carga completa"</string>
+    <string name="power_remaining_charging_duration_only" msgid="6672239353042034265">"Tempo restante até a carga completa: <xliff:g id="TIME">%1$s</xliff:g>"</string>
+    <string name="power_charging_duration" msgid="5850751284103249125">"<xliff:g id="LEVEL">%1$s</xliff:g>: <xliff:g id="TIME">%2$s</xliff:g> até a carga completa"</string>
     <string name="battery_info_status_unknown" msgid="196130600938058547">"Desconhecido"</string>
     <string name="battery_info_status_charging" msgid="1705179948350365604">"Carregando"</string>
     <string name="battery_info_status_charging_lower" msgid="8689770213898117994">"carregando"</string>
diff --git a/packages/SettingsLib/res/values-pt-rPT/strings.xml b/packages/SettingsLib/res/values-pt-rPT/strings.xml
index c076d32..a206d1a 100644
--- a/packages/SettingsLib/res/values-pt-rPT/strings.xml
+++ b/packages/SettingsLib/res/values-pt-rPT/strings.xml
@@ -402,8 +402,8 @@
     <string name="power_remaining_duration_shutdown_imminent" product="tablet" msgid="7466484148515796216">"O tablet poderá ser encerrado em breve (<xliff:g id="LEVEL">%1$s</xliff:g>)."</string>
     <string name="power_remaining_duration_shutdown_imminent" product="device" msgid="603933521600231649">"O dispositivo poderá ser encerrado em breve (<xliff:g id="LEVEL">%1$s</xliff:g>)."</string>
     <string name="power_charging" msgid="1779532561355864267">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="STATE">%2$s</xliff:g>"</string>
-    <string name="power_remaining_charging_duration_only" msgid="1421102457410268886">"Falta(m) <xliff:g id="TIME">%1$s</xliff:g> para concluir o carregamento"</string>
-    <string name="power_charging_duration" msgid="4676999980973411875">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g> até ficar totalmente carregada"</string>
+    <string name="power_remaining_charging_duration_only" msgid="6672239353042034265">"Falta(m) <xliff:g id="TIME">%1$s</xliff:g> até ficar carregada"</string>
+    <string name="power_charging_duration" msgid="5850751284103249125">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g> até ficar carregada"</string>
     <string name="battery_info_status_unknown" msgid="196130600938058547">"Desconhecido"</string>
     <string name="battery_info_status_charging" msgid="1705179948350365604">"A carregar"</string>
     <string name="battery_info_status_charging_lower" msgid="8689770213898117994">"a carregar…"</string>
diff --git a/packages/SettingsLib/res/values-pt/strings.xml b/packages/SettingsLib/res/values-pt/strings.xml
index dd0a75b..04a24f1 100644
--- a/packages/SettingsLib/res/values-pt/strings.xml
+++ b/packages/SettingsLib/res/values-pt/strings.xml
@@ -402,8 +402,8 @@
     <string name="power_remaining_duration_shutdown_imminent" product="tablet" msgid="7466484148515796216">"O tablet pode ser desligado em breve (<xliff:g id="LEVEL">%1$s</xliff:g>)"</string>
     <string name="power_remaining_duration_shutdown_imminent" product="device" msgid="603933521600231649">"O dispositivo pode ser desligado em breve (<xliff:g id="LEVEL">%1$s</xliff:g>)"</string>
     <string name="power_charging" msgid="1779532561355864267">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string>
-    <string name="power_remaining_charging_duration_only" msgid="1421102457410268886">"<xliff:g id="TIME">%1$s</xliff:g> restante(s) até a carga completa"</string>
-    <string name="power_charging_duration" msgid="4676999980973411875">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> até a carga completa"</string>
+    <string name="power_remaining_charging_duration_only" msgid="6672239353042034265">"Tempo restante até a carga completa: <xliff:g id="TIME">%1$s</xliff:g>"</string>
+    <string name="power_charging_duration" msgid="5850751284103249125">"<xliff:g id="LEVEL">%1$s</xliff:g>: <xliff:g id="TIME">%2$s</xliff:g> até a carga completa"</string>
     <string name="battery_info_status_unknown" msgid="196130600938058547">"Desconhecido"</string>
     <string name="battery_info_status_charging" msgid="1705179948350365604">"Carregando"</string>
     <string name="battery_info_status_charging_lower" msgid="8689770213898117994">"carregando"</string>
diff --git a/packages/SettingsLib/res/values-ro/strings.xml b/packages/SettingsLib/res/values-ro/strings.xml
index fb020e2..76a56e5 100644
--- a/packages/SettingsLib/res/values-ro/strings.xml
+++ b/packages/SettingsLib/res/values-ro/strings.xml
@@ -402,8 +402,8 @@
     <string name="power_remaining_duration_shutdown_imminent" product="tablet" msgid="7466484148515796216">"Tableta se poate închide în curând (<xliff:g id="LEVEL">%1$s</xliff:g>)"</string>
     <string name="power_remaining_duration_shutdown_imminent" product="device" msgid="603933521600231649">"Dispozitivul se poate închide în curând (<xliff:g id="LEVEL">%1$s</xliff:g>)"</string>
     <string name="power_charging" msgid="1779532561355864267">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string>
-    <string name="power_remaining_charging_duration_only" msgid="1421102457410268886">"Timp rămas până la încărcarea completă: <xliff:g id="TIME">%1$s</xliff:g>"</string>
-    <string name="power_charging_duration" msgid="4676999980973411875">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> până la încărcarea completă"</string>
+    <string name="power_remaining_charging_duration_only" msgid="6672239353042034265">"Au mai rămas <xliff:g id="TIME">%1$s</xliff:g> până la încărcare"</string>
+    <string name="power_charging_duration" msgid="5850751284103249125">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g> până la încărcare"</string>
     <string name="battery_info_status_unknown" msgid="196130600938058547">"Necunoscut"</string>
     <string name="battery_info_status_charging" msgid="1705179948350365604">"Se încarcă"</string>
     <string name="battery_info_status_charging_lower" msgid="8689770213898117994">"se încarcă"</string>
diff --git a/packages/SettingsLib/res/values-ru/strings.xml b/packages/SettingsLib/res/values-ru/strings.xml
index 806be6e..3e3768a 100644
--- a/packages/SettingsLib/res/values-ru/strings.xml
+++ b/packages/SettingsLib/res/values-ru/strings.xml
@@ -402,8 +402,8 @@
     <string name="power_remaining_duration_shutdown_imminent" product="tablet" msgid="7466484148515796216">"Уровень заряда батареи: <xliff:g id="LEVEL">%1$s</xliff:g>. Планшет скоро завершит работу."</string>
     <string name="power_remaining_duration_shutdown_imminent" product="device" msgid="603933521600231649">"Уровень заряда батареи: <xliff:g id="LEVEL">%1$s</xliff:g>. Устройство скоро завершит работу."</string>
     <string name="power_charging" msgid="1779532561355864267">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="STATE">%2$s</xliff:g>"</string>
-    <string name="power_remaining_charging_duration_only" msgid="1421102457410268886">"Ещё <xliff:g id="TIME">%1$s</xliff:g> до полной зарядки"</string>
-    <string name="power_charging_duration" msgid="4676999980973411875">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g> до полной зарядки"</string>
+    <string name="power_remaining_charging_duration_only" msgid="6672239353042034265">"<xliff:g id="TIME">%1$s</xliff:g> до полной зарядки"</string>
+    <string name="power_charging_duration" msgid="5850751284103249125">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g> до полной зарядки"</string>
     <string name="battery_info_status_unknown" msgid="196130600938058547">"Неизвестно"</string>
     <string name="battery_info_status_charging" msgid="1705179948350365604">"Идет зарядка"</string>
     <string name="battery_info_status_charging_lower" msgid="8689770213898117994">"заряжается"</string>
diff --git a/packages/SettingsLib/res/values-si/strings.xml b/packages/SettingsLib/res/values-si/strings.xml
index 925d5b4..186c23a 100644
--- a/packages/SettingsLib/res/values-si/strings.xml
+++ b/packages/SettingsLib/res/values-si/strings.xml
@@ -402,8 +402,8 @@
     <string name="power_remaining_duration_shutdown_imminent" product="tablet" msgid="7466484148515796216">"ටැබ්ලටය ඉක්මනින් වැසිය හැකිය (<xliff:g id="LEVEL">%1$s</xliff:g>)"</string>
     <string name="power_remaining_duration_shutdown_imminent" product="device" msgid="603933521600231649">"උපාංගය ඉක්මනින් වැසිය හැකිය (<xliff:g id="LEVEL">%1$s</xliff:g>)"</string>
     <string name="power_charging" msgid="1779532561355864267">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string>
-    <string name="power_remaining_charging_duration_only" msgid="1421102457410268886">"පූර්ණව ආරෝපණය වන තෙක් <xliff:g id="TIME">%1$s</xliff:g> ඉතිරියි"</string>
-    <string name="power_charging_duration" msgid="4676999980973411875">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> සම්පූර්ණයෙන් ආරෝපණය වන තෙක්"</string>
+    <string name="power_remaining_charging_duration_only" msgid="6672239353042034265">"ආරෝපණය වන තෙක් <xliff:g id="TIME">%1$s</xliff:g> ඇත"</string>
+    <string name="power_charging_duration" msgid="5850751284103249125">"<xliff:g id="LEVEL">%1$s</xliff:g> - ආරෝපණය වන තෙක් <xliff:g id="TIME">%2$s</xliff:g>"</string>
     <string name="battery_info_status_unknown" msgid="196130600938058547">"නොදනී"</string>
     <string name="battery_info_status_charging" msgid="1705179948350365604">"ආරෝපණය වෙමින්"</string>
     <string name="battery_info_status_charging_lower" msgid="8689770213898117994">"ආරෝපණය වේ"</string>
diff --git a/packages/SettingsLib/res/values-sk/strings.xml b/packages/SettingsLib/res/values-sk/strings.xml
index d77e1eb..9559975 100644
--- a/packages/SettingsLib/res/values-sk/strings.xml
+++ b/packages/SettingsLib/res/values-sk/strings.xml
@@ -402,8 +402,8 @@
     <string name="power_remaining_duration_shutdown_imminent" product="tablet" msgid="7466484148515796216">"Tablet sa môže čoskoro vypnúť (<xliff:g id="LEVEL">%1$s</xliff:g>)"</string>
     <string name="power_remaining_duration_shutdown_imminent" product="device" msgid="603933521600231649">"Zariadenie sa môže čoskoro vypnúť (<xliff:g id="LEVEL">%1$s</xliff:g>)"</string>
     <string name="power_charging" msgid="1779532561355864267">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="STATE">%2$s</xliff:g>"</string>
-    <string name="power_remaining_charging_duration_only" msgid="1421102457410268886">"<xliff:g id="TIME">%1$s</xliff:g> do úplného nabitia"</string>
-    <string name="power_charging_duration" msgid="4676999980973411875">"<xliff:g id="LEVEL">%1$s</xliff:g>, <xliff:g id="TIME">%2$s</xliff:g> do úplného nabitia"</string>
+    <string name="power_remaining_charging_duration_only" msgid="6672239353042034265">"Zostávajúci čas do úplného nabitia: <xliff:g id="TIME">%1$s</xliff:g>"</string>
+    <string name="power_charging_duration" msgid="5850751284103249125">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g> do úplného nabitia"</string>
     <string name="battery_info_status_unknown" msgid="196130600938058547">"Neznáme"</string>
     <string name="battery_info_status_charging" msgid="1705179948350365604">"Nabíja sa"</string>
     <string name="battery_info_status_charging_lower" msgid="8689770213898117994">"nabíja sa"</string>
diff --git a/packages/SettingsLib/res/values-sl/strings.xml b/packages/SettingsLib/res/values-sl/strings.xml
index 263b4d0..62e4ad1 100644
--- a/packages/SettingsLib/res/values-sl/strings.xml
+++ b/packages/SettingsLib/res/values-sl/strings.xml
@@ -402,8 +402,8 @@
     <string name="power_remaining_duration_shutdown_imminent" product="tablet" msgid="7466484148515796216">"Tablični računalnik se bo morda kmalu zaustavil (<xliff:g id="LEVEL">%1$s</xliff:g>)"</string>
     <string name="power_remaining_duration_shutdown_imminent" product="device" msgid="603933521600231649">"Naprava se bo morda kmalu zaustavila (<xliff:g id="LEVEL">%1$s</xliff:g>)"</string>
     <string name="power_charging" msgid="1779532561355864267">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="STATE">%2$s</xliff:g>"</string>
-    <string name="power_remaining_charging_duration_only" msgid="1421102457410268886">"Še <xliff:g id="TIME">%1$s</xliff:g> do polne napolnjenosti"</string>
-    <string name="power_charging_duration" msgid="4676999980973411875">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g> do napolnjenosti"</string>
+    <string name="power_remaining_charging_duration_only" msgid="6672239353042034265">"Še <xliff:g id="TIME">%1$s</xliff:g> do polne napolnjenosti"</string>
+    <string name="power_charging_duration" msgid="5850751284103249125">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g> do polne napolnjenosti"</string>
     <string name="battery_info_status_unknown" msgid="196130600938058547">"Neznano"</string>
     <string name="battery_info_status_charging" msgid="1705179948350365604">"Polnjenje"</string>
     <string name="battery_info_status_charging_lower" msgid="8689770213898117994">"polnjenje"</string>
diff --git a/packages/SettingsLib/res/values-sq/strings.xml b/packages/SettingsLib/res/values-sq/strings.xml
index 7a054bb..0498f31 100644
--- a/packages/SettingsLib/res/values-sq/strings.xml
+++ b/packages/SettingsLib/res/values-sq/strings.xml
@@ -402,8 +402,8 @@
     <string name="power_remaining_duration_shutdown_imminent" product="tablet" msgid="7466484148515796216">"Tableti mund të fiket së shpejti (<xliff:g id="LEVEL">%1$s</xliff:g>)"</string>
     <string name="power_remaining_duration_shutdown_imminent" product="device" msgid="603933521600231649">"Pajisja mund të fiket së shpejti (<xliff:g id="LEVEL">%1$s</xliff:g>)"</string>
     <string name="power_charging" msgid="1779532561355864267">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string>
-    <string name="power_remaining_charging_duration_only" msgid="1421102457410268886">"<xliff:g id="TIME">%1$s</xliff:g> të mbetura deri në ngarkimin e plotë"</string>
-    <string name="power_charging_duration" msgid="4676999980973411875">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> derisa të mbushet plotësisht"</string>
+    <string name="power_remaining_charging_duration_only" msgid="6672239353042034265">"<xliff:g id="TIME">%1$s</xliff:g> të mbetura për karikimin"</string>
+    <string name="power_charging_duration" msgid="5850751284103249125">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> deri sa të karikohen"</string>
     <string name="battery_info_status_unknown" msgid="196130600938058547">"I panjohur"</string>
     <string name="battery_info_status_charging" msgid="1705179948350365604">"Po karikohet"</string>
     <string name="battery_info_status_charging_lower" msgid="8689770213898117994">"po karikohet"</string>
diff --git a/packages/SettingsLib/res/values-sr/strings.xml b/packages/SettingsLib/res/values-sr/strings.xml
index 0edc985..3157dee 100644
--- a/packages/SettingsLib/res/values-sr/strings.xml
+++ b/packages/SettingsLib/res/values-sr/strings.xml
@@ -402,8 +402,8 @@
     <string name="power_remaining_duration_shutdown_imminent" product="tablet" msgid="7466484148515796216">"Таблет ће се ускоро искључити (<xliff:g id="LEVEL">%1$s</xliff:g>)"</string>
     <string name="power_remaining_duration_shutdown_imminent" product="device" msgid="603933521600231649">"Уређај ће се ускоро искључити (<xliff:g id="LEVEL">%1$s</xliff:g>)"</string>
     <string name="power_charging" msgid="1779532561355864267">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="STATE">%2$s</xliff:g>"</string>
-    <string name="power_remaining_charging_duration_only" msgid="1421102457410268886">"<xliff:g id="TIME">%1$s</xliff:g> до потпуног пуњења"</string>
-    <string name="power_charging_duration" msgid="4676999980973411875">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g> до потпуног пуњења"</string>
+    <string name="power_remaining_charging_duration_only" msgid="6672239353042034265">"Напуниће се за <xliff:g id="TIME">%1$s</xliff:g>"</string>
+    <string name="power_charging_duration" msgid="5850751284103249125">"<xliff:g id="LEVEL">%1$s</xliff:g> – напуниће се за <xliff:g id="TIME">%2$s</xliff:g>"</string>
     <string name="battery_info_status_unknown" msgid="196130600938058547">"Непознато"</string>
     <string name="battery_info_status_charging" msgid="1705179948350365604">"Пуни се"</string>
     <string name="battery_info_status_charging_lower" msgid="8689770213898117994">"пуни се"</string>
diff --git a/packages/SettingsLib/res/values-sv/strings.xml b/packages/SettingsLib/res/values-sv/strings.xml
index 862fc6c..31517b8 100644
--- a/packages/SettingsLib/res/values-sv/strings.xml
+++ b/packages/SettingsLib/res/values-sv/strings.xml
@@ -402,8 +402,8 @@
     <string name="power_remaining_duration_shutdown_imminent" product="tablet" msgid="7466484148515796216">"Surfplattan kan stängas av snart (<xliff:g id="LEVEL">%1$s</xliff:g>)"</string>
     <string name="power_remaining_duration_shutdown_imminent" product="device" msgid="603933521600231649">"Enheten kan stängas av snart (<xliff:g id="LEVEL">%1$s</xliff:g>)"</string>
     <string name="power_charging" msgid="1779532561355864267">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="STATE">%2$s</xliff:g>"</string>
-    <string name="power_remaining_charging_duration_only" msgid="1421102457410268886">"Batteriet är fulladdat om <xliff:g id="TIME">%1$s</xliff:g>"</string>
-    <string name="power_charging_duration" msgid="4676999980973411875">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g> tills det är fulladdat"</string>
+    <string name="power_remaining_charging_duration_only" msgid="6672239353042034265">"<xliff:g id="TIME">%1$s</xliff:g> kvar till full laddning"</string>
+    <string name="power_charging_duration" msgid="5850751284103249125">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g> till full laddning"</string>
     <string name="battery_info_status_unknown" msgid="196130600938058547">"Okänd"</string>
     <string name="battery_info_status_charging" msgid="1705179948350365604">"Laddar"</string>
     <string name="battery_info_status_charging_lower" msgid="8689770213898117994">"laddas"</string>
diff --git a/packages/SettingsLib/res/values-sw/strings.xml b/packages/SettingsLib/res/values-sw/strings.xml
index 12922ca..d73084f 100644
--- a/packages/SettingsLib/res/values-sw/strings.xml
+++ b/packages/SettingsLib/res/values-sw/strings.xml
@@ -402,8 +402,8 @@
     <string name="power_remaining_duration_shutdown_imminent" product="tablet" msgid="7466484148515796216">"Kompyuta kibao inakaribia kuzimika (<xliff:g id="LEVEL">%1$s</xliff:g>)"</string>
     <string name="power_remaining_duration_shutdown_imminent" product="device" msgid="603933521600231649">"Kifaa kinakaribia kuzimika (<xliff:g id="LEVEL">%1$s</xliff:g>)"</string>
     <string name="power_charging" msgid="1779532561355864267">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string>
-    <string name="power_remaining_charging_duration_only" msgid="1421102457410268886">"Imebaki <xliff:g id="TIME">%1$s</xliff:g> chaji ijae"</string>
-    <string name="power_charging_duration" msgid="4676999980973411875">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> hadi ijae chaji"</string>
+    <string name="power_remaining_charging_duration_only" msgid="6672239353042034265">"Zimesalia <xliff:g id="TIME">%1$s</xliff:g> hadi ijae chaji"</string>
+    <string name="power_charging_duration" msgid="5850751284103249125">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> hadi ijae chaji"</string>
     <string name="battery_info_status_unknown" msgid="196130600938058547">"Haijulikani"</string>
     <string name="battery_info_status_charging" msgid="1705179948350365604">"Inachaji"</string>
     <string name="battery_info_status_charging_lower" msgid="8689770213898117994">"inachaji"</string>
diff --git a/packages/SettingsLib/res/values-ta/strings.xml b/packages/SettingsLib/res/values-ta/strings.xml
index 8f72ab6..de70d08 100644
--- a/packages/SettingsLib/res/values-ta/strings.xml
+++ b/packages/SettingsLib/res/values-ta/strings.xml
@@ -138,8 +138,8 @@
     <string name="accessibility_wifi_security_type_none" msgid="1223747559986205423">"கடவுச்சொல் தேவைப்படாத திறந்த நெட்வொர்க்"</string>
     <string name="accessibility_wifi_security_type_secured" msgid="862921720418885331">"கடவுச்சொல் தேவைப்படும் பாதுகாப்பான நெட்வொர்க்"</string>
     <string name="process_kernel_label" msgid="3916858646836739323">"Android OS"</string>
-    <string name="data_usage_uninstalled_apps" msgid="614263770923231598">"அகற்றப்பட்ட பயன்பாடுகள்"</string>
-    <string name="data_usage_uninstalled_apps_users" msgid="7986294489899813194">"அகற்றப்பட்ட பயன்பாடுகள் மற்றும் பயனர்கள்"</string>
+    <string name="data_usage_uninstalled_apps" msgid="614263770923231598">"அகற்றப்பட்ட ஆப்ஸ்"</string>
+    <string name="data_usage_uninstalled_apps_users" msgid="7986294489899813194">"அகற்றப்பட்ட ஆப்ஸ் மற்றும் பயனர்கள்"</string>
     <string name="data_usage_ota" msgid="5377889154805560860">"சிஸ்டம் புதுப்பிப்புகள்"</string>
     <string name="tether_settings_title_usb" msgid="6688416425801386511">"USB டெதெரிங்"</string>
     <string name="tether_settings_title_wifi" msgid="3277144155960302049">"போர்ட்டபிள் ஹாட்ஸ்பாட்"</string>
@@ -402,8 +402,8 @@
     <string name="power_remaining_duration_shutdown_imminent" product="tablet" msgid="7466484148515796216">"டேப்லெட் விரைவில் ஆஃப் ஆகக்கூடும் (<xliff:g id="LEVEL">%1$s</xliff:g>)"</string>
     <string name="power_remaining_duration_shutdown_imminent" product="device" msgid="603933521600231649">"சாதனம் விரைவில் ஆஃப் ஆகக்கூடும் (<xliff:g id="LEVEL">%1$s</xliff:g>)"</string>
     <string name="power_charging" msgid="1779532561355864267">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string>
-    <string name="power_remaining_charging_duration_only" msgid="1421102457410268886">"முழு சார்ஜாக <xliff:g id="TIME">%1$s</xliff:g>ம் ஆகும்"</string>
-    <string name="power_charging_duration" msgid="4676999980973411875">"<xliff:g id="LEVEL">%1$s</xliff:g> - முழு சார்ஜாக <xliff:g id="TIME">%2$s</xliff:g> ஆகும்"</string>
+    <string name="power_remaining_charging_duration_only" msgid="6672239353042034265">"முழு சார்ஜாக <xliff:g id="TIME">%1$s</xliff:g> ஆகும்"</string>
+    <string name="power_charging_duration" msgid="5850751284103249125">"<xliff:g id="LEVEL">%1$s</xliff:g> - முழு சார்ஜாக <xliff:g id="TIME">%2$s</xliff:g> ஆகும்"</string>
     <string name="battery_info_status_unknown" msgid="196130600938058547">"அறியப்படாத"</string>
     <string name="battery_info_status_charging" msgid="1705179948350365604">"சார்ஜ் ஆகிறது"</string>
     <string name="battery_info_status_charging_lower" msgid="8689770213898117994">"சார்ஜ் ஆகிறது"</string>
diff --git a/packages/SettingsLib/res/values-te/strings.xml b/packages/SettingsLib/res/values-te/strings.xml
index e591121..3591670 100644
--- a/packages/SettingsLib/res/values-te/strings.xml
+++ b/packages/SettingsLib/res/values-te/strings.xml
@@ -402,8 +402,8 @@
     <string name="power_remaining_duration_shutdown_imminent" product="tablet" msgid="7466484148515796216">"టాబ్లెట్ షట్‌డౌన్ కావచ్చు (<xliff:g id="LEVEL">%1$s</xliff:g>)"</string>
     <string name="power_remaining_duration_shutdown_imminent" product="device" msgid="603933521600231649">"పరికరం త్వరలో షట్‌డౌన్ కావచ్చు (<xliff:g id="LEVEL">%1$s</xliff:g>)"</string>
     <string name="power_charging" msgid="1779532561355864267">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string>
-    <string name="power_remaining_charging_duration_only" msgid="1421102457410268886">"పూర్తిగా ఛార్జ్ కావడానికి <xliff:g id="TIME">%1$s</xliff:g> పడుతుంది"</string>
-    <string name="power_charging_duration" msgid="4676999980973411875">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g>లో పూర్తిగా ఛార్జ్ అవుతుంది"</string>
+    <string name="power_remaining_charging_duration_only" msgid="6672239353042034265">"ఛార్జ్ అవ్వడానికి <xliff:g id="TIME">%1$s</xliff:g> సమయం మిగిలి ఉంది"</string>
+    <string name="power_charging_duration" msgid="5850751284103249125">"<xliff:g id="LEVEL">%1$s</xliff:g> - ఛార్జ్ అవ్వడానికి <xliff:g id="TIME">%2$s</xliff:g> పడుతుంది"</string>
     <string name="battery_info_status_unknown" msgid="196130600938058547">"తెలియదు"</string>
     <string name="battery_info_status_charging" msgid="1705179948350365604">"ఛార్జ్ అవుతోంది"</string>
     <string name="battery_info_status_charging_lower" msgid="8689770213898117994">"ఛార్జ్ అవుతోంది"</string>
diff --git a/packages/SettingsLib/res/values-th/strings.xml b/packages/SettingsLib/res/values-th/strings.xml
index b3bef9d..1cfe45e 100644
--- a/packages/SettingsLib/res/values-th/strings.xml
+++ b/packages/SettingsLib/res/values-th/strings.xml
@@ -402,8 +402,8 @@
     <string name="power_remaining_duration_shutdown_imminent" product="tablet" msgid="7466484148515796216">"แท็บเล็ตอาจปิดเครื่องในไม่ช้า (<xliff:g id="LEVEL">%1$s</xliff:g>)"</string>
     <string name="power_remaining_duration_shutdown_imminent" product="device" msgid="603933521600231649">"อุปกรณ์อาจปิดเครื่องในไม่ช้า (<xliff:g id="LEVEL">%1$s</xliff:g>)"</string>
     <string name="power_charging" msgid="1779532561355864267">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string>
-    <string name="power_remaining_charging_duration_only" msgid="1421102457410268886">"อีก <xliff:g id="TIME">%1$s</xliff:g> จึงจะชาร์จเต็ม"</string>
-    <string name="power_charging_duration" msgid="4676999980973411875">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g>จนกว่าจะชาร์จเต็ม"</string>
+    <string name="power_remaining_charging_duration_only" msgid="6672239353042034265">"เหลือ <xliff:g id="TIME">%1$s</xliff:g> จนกว่าจะชาร์จ"</string>
+    <string name="power_charging_duration" msgid="5850751284103249125">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> จนกว่าจะชาร์จ"</string>
     <string name="battery_info_status_unknown" msgid="196130600938058547">"ไม่ทราบ"</string>
     <string name="battery_info_status_charging" msgid="1705179948350365604">"กำลังชาร์จ"</string>
     <string name="battery_info_status_charging_lower" msgid="8689770213898117994">"กำลังชาร์จ"</string>
diff --git a/packages/SettingsLib/res/values-tl/strings.xml b/packages/SettingsLib/res/values-tl/strings.xml
index 85b6438..8b3118b 100644
--- a/packages/SettingsLib/res/values-tl/strings.xml
+++ b/packages/SettingsLib/res/values-tl/strings.xml
@@ -402,8 +402,8 @@
     <string name="power_remaining_duration_shutdown_imminent" product="tablet" msgid="7466484148515796216">"Malapit nang mag-shutdown ang tablet (<xliff:g id="LEVEL">%1$s</xliff:g>)"</string>
     <string name="power_remaining_duration_shutdown_imminent" product="device" msgid="603933521600231649">"Malapit nang mag-shut down ang device (<xliff:g id="LEVEL">%1$s</xliff:g>)"</string>
     <string name="power_charging" msgid="1779532561355864267">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string>
-    <string name="power_remaining_charging_duration_only" msgid="1421102457410268886">"<xliff:g id="TIME">%1$s</xliff:g> ang natitira bago makumpleto ang charge"</string>
-    <string name="power_charging_duration" msgid="4676999980973411875">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> hanggang sa makumpleto ang charge"</string>
+    <string name="power_remaining_charging_duration_only" msgid="6672239353042034265">"<xliff:g id="TIME">%1$s</xliff:g> ang natitira bago matapos mag-charge"</string>
+    <string name="power_charging_duration" msgid="5850751284103249125">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> hanggang matapos mag-charge"</string>
     <string name="battery_info_status_unknown" msgid="196130600938058547">"Hindi Kilala"</string>
     <string name="battery_info_status_charging" msgid="1705179948350365604">"Nagcha-charge"</string>
     <string name="battery_info_status_charging_lower" msgid="8689770213898117994">"nagcha-charge"</string>
diff --git a/packages/SettingsLib/res/values-tr/strings.xml b/packages/SettingsLib/res/values-tr/strings.xml
index 6031eca..5891c79 100644
--- a/packages/SettingsLib/res/values-tr/strings.xml
+++ b/packages/SettingsLib/res/values-tr/strings.xml
@@ -402,8 +402,8 @@
     <string name="power_remaining_duration_shutdown_imminent" product="tablet" msgid="7466484148515796216">"Tablet kısa süre içinde kapanabilir (<xliff:g id="LEVEL">%1$s</xliff:g>)"</string>
     <string name="power_remaining_duration_shutdown_imminent" product="device" msgid="603933521600231649">"Cihaz kısa süre içinde kapanabilir (<xliff:g id="LEVEL">%1$s</xliff:g>)"</string>
     <string name="power_charging" msgid="1779532561355864267">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string>
-    <string name="power_remaining_charging_duration_only" msgid="1421102457410268886">"Tam olarak şarj olmasına <xliff:g id="TIME">%1$s</xliff:g> kaldı"</string>
-    <string name="power_charging_duration" msgid="4676999980973411875">"<xliff:g id="LEVEL">%1$s</xliff:g> - Tam şarj olmasına <xliff:g id="TIME">%2$s</xliff:g> kaldı"</string>
+    <string name="power_remaining_charging_duration_only" msgid="6672239353042034265">"Şarj olmaya <xliff:g id="TIME">%1$s</xliff:g> kaldı"</string>
+    <string name="power_charging_duration" msgid="5850751284103249125">"<xliff:g id="LEVEL">%1$s</xliff:g> - şarj olmaya <xliff:g id="TIME">%2$s</xliff:g> kaldı"</string>
     <string name="battery_info_status_unknown" msgid="196130600938058547">"Bilinmiyor"</string>
     <string name="battery_info_status_charging" msgid="1705179948350365604">"Şarj oluyor"</string>
     <string name="battery_info_status_charging_lower" msgid="8689770213898117994">"şarj oluyor"</string>
diff --git a/packages/SettingsLib/res/values-uk/strings.xml b/packages/SettingsLib/res/values-uk/strings.xml
index 5f3c6a6..0bca307 100644
--- a/packages/SettingsLib/res/values-uk/strings.xml
+++ b/packages/SettingsLib/res/values-uk/strings.xml
@@ -402,8 +402,8 @@
     <string name="power_remaining_duration_shutdown_imminent" product="tablet" msgid="7466484148515796216">"Планшет може невдовзі вимкнутися (<xliff:g id="LEVEL">%1$s</xliff:g>)"</string>
     <string name="power_remaining_duration_shutdown_imminent" product="device" msgid="603933521600231649">"Пристрій може невдовзі вимкнутися (<xliff:g id="LEVEL">%1$s</xliff:g>)"</string>
     <string name="power_charging" msgid="1779532561355864267">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="STATE">%2$s</xliff:g>"</string>
-    <string name="power_remaining_charging_duration_only" msgid="1421102457410268886">"До повного зарядження залишилося <xliff:g id="TIME">%1$s</xliff:g>"</string>
-    <string name="power_charging_duration" msgid="4676999980973411875">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g> до повного заряду"</string>
+    <string name="power_remaining_charging_duration_only" msgid="6672239353042034265">"<xliff:g id="TIME">%1$s</xliff:g> до повного заряду"</string>
+    <string name="power_charging_duration" msgid="5850751284103249125">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g> до повного заряду"</string>
     <string name="battery_info_status_unknown" msgid="196130600938058547">"Невідомо"</string>
     <string name="battery_info_status_charging" msgid="1705179948350365604">"Заряджається"</string>
     <string name="battery_info_status_charging_lower" msgid="8689770213898117994">"заряджається"</string>
diff --git a/packages/SettingsLib/res/values-ur/strings.xml b/packages/SettingsLib/res/values-ur/strings.xml
index 82d9b3f..1e27b48 100644
--- a/packages/SettingsLib/res/values-ur/strings.xml
+++ b/packages/SettingsLib/res/values-ur/strings.xml
@@ -402,8 +402,8 @@
     <string name="power_remaining_duration_shutdown_imminent" product="tablet" msgid="7466484148515796216">"ٹیبلیٹ جلد ہی بند ہو سکتا ہے (<xliff:g id="LEVEL">%1$s</xliff:g>)"</string>
     <string name="power_remaining_duration_shutdown_imminent" product="device" msgid="603933521600231649">"آلہ جلد ہی بند ہو سکتا ہے (<xliff:g id="LEVEL">%1$s</xliff:g>)"</string>
     <string name="power_charging" msgid="1779532561355864267">"‎<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>‎"</string>
-    <string name="power_remaining_charging_duration_only" msgid="1421102457410268886">"پوری طرح چارج ہونے میں <xliff:g id="TIME">%1$s</xliff:g> باقی ہے"</string>
-    <string name="power_charging_duration" msgid="4676999980973411875">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> پوری طرح چارج ہونے تک"</string>
+    <string name="power_remaining_charging_duration_only" msgid="6672239353042034265">"چارج ہونے میں <xliff:g id="TIME">%1$s</xliff:g> باقی"</string>
+    <string name="power_charging_duration" msgid="5850751284103249125">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> چارج ہونے تک"</string>
     <string name="battery_info_status_unknown" msgid="196130600938058547">"نامعلوم"</string>
     <string name="battery_info_status_charging" msgid="1705179948350365604">"چارج ہو رہا ہے"</string>
     <string name="battery_info_status_charging_lower" msgid="8689770213898117994">"چارج ہو رہا ہے"</string>
diff --git a/packages/SettingsLib/res/values-uz/strings.xml b/packages/SettingsLib/res/values-uz/strings.xml
index 0d3e8de..487100c 100644
--- a/packages/SettingsLib/res/values-uz/strings.xml
+++ b/packages/SettingsLib/res/values-uz/strings.xml
@@ -402,8 +402,8 @@
     <string name="power_remaining_duration_shutdown_imminent" product="tablet" msgid="7466484148515796216">"Planshet tez orada o‘chib qolishi mumkin (<xliff:g id="LEVEL">%1$s</xliff:g>)"</string>
     <string name="power_remaining_duration_shutdown_imminent" product="device" msgid="603933521600231649">"Qurilma tez orada o‘chib qolishi mumkin (<xliff:g id="LEVEL">%1$s</xliff:g>)"</string>
     <string name="power_charging" msgid="1779532561355864267">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="STATE">%2$s</xliff:g>"</string>
-    <string name="power_remaining_charging_duration_only" msgid="1421102457410268886">"To‘lishiga <xliff:g id="TIME">%1$s</xliff:g> qoldi"</string>
-    <string name="power_charging_duration" msgid="4676999980973411875">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g> ichida to‘ladi"</string>
+    <string name="power_remaining_charging_duration_only" msgid="6672239353042034265">"<xliff:g id="TIME">%1$s</xliff:g> ichida toʻliq quvvat oladi"</string>
+    <string name="power_charging_duration" msgid="5850751284103249125">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g> ichida toʻliq quvvat oladi"</string>
     <string name="battery_info_status_unknown" msgid="196130600938058547">"Noma’lum"</string>
     <string name="battery_info_status_charging" msgid="1705179948350365604">"Quvvat olmoqda"</string>
     <string name="battery_info_status_charging_lower" msgid="8689770213898117994">"quvvat olmoqda"</string>
diff --git a/packages/SettingsLib/res/values-vi/strings.xml b/packages/SettingsLib/res/values-vi/strings.xml
index 003c457..c247617 100644
--- a/packages/SettingsLib/res/values-vi/strings.xml
+++ b/packages/SettingsLib/res/values-vi/strings.xml
@@ -402,8 +402,8 @@
     <string name="power_remaining_duration_shutdown_imminent" product="tablet" msgid="7466484148515796216">"Máy tính bảng có thể sắp tắt (<xliff:g id="LEVEL">%1$s</xliff:g>)"</string>
     <string name="power_remaining_duration_shutdown_imminent" product="device" msgid="603933521600231649">"Thiết bị có thể sắp tắt (<xliff:g id="LEVEL">%1$s</xliff:g>)"</string>
     <string name="power_charging" msgid="1779532561355864267">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string>
-    <string name="power_remaining_charging_duration_only" msgid="1421102457410268886">"<xliff:g id="TIME">%1$s</xliff:g> nữa sẽ được sạc đầy"</string>
-    <string name="power_charging_duration" msgid="4676999980973411875">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> nữa sẽ được sạc đầy"</string>
+    <string name="power_remaining_charging_duration_only" msgid="6672239353042034265">"Còn <xliff:g id="TIME">%1$s</xliff:g> nữa là sạc xong"</string>
+    <string name="power_charging_duration" msgid="5850751284103249125">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g> nữa là sạc xong"</string>
     <string name="battery_info_status_unknown" msgid="196130600938058547">"Không xác định"</string>
     <string name="battery_info_status_charging" msgid="1705179948350365604">"Đang sạc"</string>
     <string name="battery_info_status_charging_lower" msgid="8689770213898117994">"đang sạc"</string>
diff --git a/packages/SettingsLib/res/values-zh-rCN/strings.xml b/packages/SettingsLib/res/values-zh-rCN/strings.xml
index bcf1f2d..dddc107 100644
--- a/packages/SettingsLib/res/values-zh-rCN/strings.xml
+++ b/packages/SettingsLib/res/values-zh-rCN/strings.xml
@@ -402,8 +402,8 @@
     <string name="power_remaining_duration_shutdown_imminent" product="tablet" msgid="7466484148515796216">"平板电脑可能即将关机 (<xliff:g id="LEVEL">%1$s</xliff:g>)"</string>
     <string name="power_remaining_duration_shutdown_imminent" product="device" msgid="603933521600231649">"设备可能即将关机 (<xliff:g id="LEVEL">%1$s</xliff:g>)"</string>
     <string name="power_charging" msgid="1779532561355864267">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string>
-    <string name="power_remaining_charging_duration_only" msgid="1421102457410268886">"还需 <xliff:g id="TIME">%1$s</xliff:g>充满电"</string>
-    <string name="power_charging_duration" msgid="4676999980973411875">"<xliff:g id="LEVEL">%1$s</xliff:g> - 还需 <xliff:g id="TIME">%2$s</xliff:g>充满"</string>
+    <string name="power_remaining_charging_duration_only" msgid="6672239353042034265">"还剩 <xliff:g id="TIME">%1$s</xliff:g>充满电"</string>
+    <string name="power_charging_duration" msgid="5850751284103249125">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g>后充满电"</string>
     <string name="battery_info_status_unknown" msgid="196130600938058547">"未知"</string>
     <string name="battery_info_status_charging" msgid="1705179948350365604">"正在充电"</string>
     <string name="battery_info_status_charging_lower" msgid="8689770213898117994">"正在充电"</string>
diff --git a/packages/SettingsLib/res/values-zh-rHK/strings.xml b/packages/SettingsLib/res/values-zh-rHK/strings.xml
index 286765d..8560e22 100644
--- a/packages/SettingsLib/res/values-zh-rHK/strings.xml
+++ b/packages/SettingsLib/res/values-zh-rHK/strings.xml
@@ -402,8 +402,8 @@
     <string name="power_remaining_duration_shutdown_imminent" product="tablet" msgid="7466484148515796216">"平板電腦可能即將關機 (<xliff:g id="LEVEL">%1$s</xliff:g>)"</string>
     <string name="power_remaining_duration_shutdown_imminent" product="device" msgid="603933521600231649">"裝置可能即將關機 (<xliff:g id="LEVEL">%1$s</xliff:g>)"</string>
     <string name="power_charging" msgid="1779532561355864267">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string>
-    <string name="power_remaining_charging_duration_only" msgid="1421102457410268886">"<xliff:g id="TIME">%1$s</xliff:g>後就能充滿電"</string>
-    <string name="power_charging_duration" msgid="4676999980973411875">"<xliff:g id="LEVEL">%1$s</xliff:g> - 還需 <xliff:g id="TIME">%2$s</xliff:g>才能充滿電"</string>
+    <string name="power_remaining_charging_duration_only" msgid="6672239353042034265">"還需 <xliff:g id="TIME">%1$s</xliff:g>才能充滿電"</string>
+    <string name="power_charging_duration" msgid="5850751284103249125">"<xliff:g id="LEVEL">%1$s</xliff:g> - 還需 <xliff:g id="TIME">%2$s</xliff:g>才能充滿電"</string>
     <string name="battery_info_status_unknown" msgid="196130600938058547">"未知"</string>
     <string name="battery_info_status_charging" msgid="1705179948350365604">"充電中"</string>
     <string name="battery_info_status_charging_lower" msgid="8689770213898117994">"正在充電"</string>
diff --git a/packages/SettingsLib/res/values-zh-rTW/strings.xml b/packages/SettingsLib/res/values-zh-rTW/strings.xml
index c641302..404aa19 100644
--- a/packages/SettingsLib/res/values-zh-rTW/strings.xml
+++ b/packages/SettingsLib/res/values-zh-rTW/strings.xml
@@ -402,8 +402,8 @@
     <string name="power_remaining_duration_shutdown_imminent" product="tablet" msgid="7466484148515796216">"平板電腦可能即將關機 (<xliff:g id="LEVEL">%1$s</xliff:g>)"</string>
     <string name="power_remaining_duration_shutdown_imminent" product="device" msgid="603933521600231649">"裝置可能即將關機 (<xliff:g id="LEVEL">%1$s</xliff:g>)"</string>
     <string name="power_charging" msgid="1779532561355864267">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string>
-    <string name="power_remaining_charging_duration_only" msgid="1421102457410268886">"再過 <xliff:g id="TIME">%1$s</xliff:g>就能完成充電"</string>
-    <string name="power_charging_duration" msgid="4676999980973411875">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g>後充飽"</string>
+    <string name="power_remaining_charging_duration_only" msgid="6672239353042034265">"<xliff:g id="TIME">%1$s</xliff:g>後充飽電"</string>
+    <string name="power_charging_duration" msgid="5850751284103249125">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g>後充飽電"</string>
     <string name="battery_info_status_unknown" msgid="196130600938058547">"不明"</string>
     <string name="battery_info_status_charging" msgid="1705179948350365604">"充電中"</string>
     <string name="battery_info_status_charging_lower" msgid="8689770213898117994">"充電中"</string>
diff --git a/packages/SettingsLib/res/values-zu/strings.xml b/packages/SettingsLib/res/values-zu/strings.xml
index 1bfbf07..542332f 100644
--- a/packages/SettingsLib/res/values-zu/strings.xml
+++ b/packages/SettingsLib/res/values-zu/strings.xml
@@ -402,8 +402,8 @@
     <string name="power_remaining_duration_shutdown_imminent" product="tablet" msgid="7466484148515796216">"Ithebhulethi ingacisha maduze (<xliff:g id="LEVEL">%1$s</xliff:g>)"</string>
     <string name="power_remaining_duration_shutdown_imminent" product="device" msgid="603933521600231649">"Idivayisi ingacisha maduze (<xliff:g id="LEVEL">%1$s</xliff:g>)"</string>
     <string name="power_charging" msgid="1779532561355864267">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string>
-    <string name="power_remaining_charging_duration_only" msgid="1421102457410268886">"<xliff:g id="TIME">%1$s</xliff:g> kushiywe ishaja"</string>
-    <string name="power_charging_duration" msgid="4676999980973411875">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> kuze ligcwale ngokuphelele"</string>
+    <string name="power_remaining_charging_duration_only" msgid="6672239353042034265">"<xliff:g id="TIME">%1$s</xliff:g> esele ize ishaje"</string>
+    <string name="power_charging_duration" msgid="5850751284103249125">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> ize igcwale"</string>
     <string name="battery_info_status_unknown" msgid="196130600938058547">"Akwaziwa"</string>
     <string name="battery_info_status_charging" msgid="1705179948350365604">"Iyashaja"</string>
     <string name="battery_info_status_charging_lower" msgid="8689770213898117994">"iyashaja"</string>
diff --git a/packages/SettingsLib/src/com/android/settingslib/location/RecentLocationAccesses.java b/packages/SettingsLib/src/com/android/settingslib/location/RecentLocationAccesses.java
index ea39317..81ca9ea 100644
--- a/packages/SettingsLib/src/com/android/settingslib/location/RecentLocationAccesses.java
+++ b/packages/SettingsLib/src/com/android/settingslib/location/RecentLocationAccesses.java
@@ -111,8 +111,9 @@
             for (int op : LOCATION_OPS) {
                 final String permission = AppOpsManager.opToPermission(op);
                 final int permissionFlags = pm.getPermissionFlags(permission, packageName, user);
-                if (PermissionChecker.checkPermission(mContext, permission, -1, uid, packageName)
-                        == PermissionChecker.PERMISSION_GRANTED) {
+                if (PermissionChecker.checkPermissionForPreflight(mContext, permission,
+                        PermissionChecker.PID_UNKNOWN, uid, packageName)
+                                == PermissionChecker.PERMISSION_GRANTED) {
                     if ((permissionFlags
                             & PackageManager.FLAG_PERMISSION_USER_SENSITIVE_WHEN_GRANTED) == 0) {
                         showApp = false;
diff --git a/packages/SettingsLib/src/com/android/settingslib/location/RecentLocationApps.java b/packages/SettingsLib/src/com/android/settingslib/location/RecentLocationApps.java
index 60c9984..104cc8f 100644
--- a/packages/SettingsLib/src/com/android/settingslib/location/RecentLocationApps.java
+++ b/packages/SettingsLib/src/com/android/settingslib/location/RecentLocationApps.java
@@ -110,9 +110,9 @@
                     final String permission = AppOpsManager.opToPermission(op);
                     final int permissionFlags = pm.getPermissionFlags(permission, packageName,
                             user);
-                    if (PermissionChecker.checkPermission(mContext, permission, -1, uid,
-                            packageName)
-                            == PermissionChecker.PERMISSION_GRANTED) {
+                    if (PermissionChecker.checkPermissionForPreflight(mContext, permission,
+                            PermissionChecker.PID_UNKNOWN, uid, packageName)
+                                    == PermissionChecker.PERMISSION_GRANTED) {
                         if ((permissionFlags
                                 & PackageManager.FLAG_PERMISSION_USER_SENSITIVE_WHEN_GRANTED)
                                 == 0) {
diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/drawer/TileTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/drawer/TileTest.java
index 5da6205..2664ecd 100644
--- a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/drawer/TileTest.java
+++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/drawer/TileTest.java
@@ -23,7 +23,6 @@
 import org.robolectric.RuntimeEnvironment;
 import org.robolectric.shadow.api.Shadow;
 import org.robolectric.shadows.ShadowPackageManager;
-import org.robolectric.util.ReflectionHelpers;
 
 @RunWith(RobolectricTestRunner.class)
 public class TileTest {
@@ -41,7 +40,7 @@
         mActivityInfo.name = "abc";
         mActivityInfo.icon = com.android.internal.R.drawable.ic_plus;
         mActivityInfo.metaData = new Bundle();
-        mTile = new Tile(mActivityInfo, "category");
+        mTile = new ActivityTile(mActivityInfo, "category");
     }
 
     @Test
@@ -70,7 +69,7 @@
     @Test
     public void getIcon_noContextOrMetadata_returnNull() {
         mActivityInfo.metaData = null;
-        final Tile tile = new Tile(mActivityInfo, "category");
+        final Tile tile = new ActivityTile(mActivityInfo, "category");
         assertThat(tile.getIcon(null)).isNull();
         assertThat(tile.getIcon(RuntimeEnvironment.application)).isNull();
     }
@@ -100,7 +99,7 @@
 
     @Test
     public void isIconTintable_hasMetadata_shouldReturnIconTintableMetadata() {
-        final Tile tile = new Tile(mActivityInfo, "category");
+        final Tile tile = new ActivityTile(mActivityInfo, "category");
 
         mActivityInfo.metaData.putBoolean(TileUtils.META_DATA_PREFERENCE_ICON_TINTABLE, false);
         assertThat(tile.isIconTintable(RuntimeEnvironment.application)).isFalse();
@@ -111,14 +110,14 @@
 
     @Test
     public void isIconTintable_noIcon_shouldReturnFalse() {
-        final Tile tile = new Tile(mActivityInfo, "category");
+        final Tile tile = new ActivityTile(mActivityInfo, "category");
 
         assertThat(tile.isIconTintable(RuntimeEnvironment.application)).isFalse();
     }
 
     @Test
     public void isIconTintable_noTintableMetadata_shouldReturnFalse() {
-        final Tile tile = new Tile(mActivityInfo, "category");
+        final Tile tile = new ActivityTile(mActivityInfo, "category");
         mActivityInfo.metaData.putInt(META_DATA_PREFERENCE_ICON, android.R.drawable.ic_info);
 
         assertThat(tile.isIconTintable(RuntimeEnvironment.application)).isFalse();
@@ -126,7 +125,7 @@
 
     @Test
     public void getPriority_noMetadata_return0() {
-        final Tile tile = new Tile(mActivityInfo, "category");
+        final Tile tile = new ActivityTile(mActivityInfo, "category");
 
         assertThat(tile.getOrder()).isEqualTo(0);
     }
@@ -135,7 +134,7 @@
     public void getPriority_badMetadata_return0() {
         mActivityInfo.metaData.putString(META_DATA_KEY_ORDER, "1");
 
-        final Tile tile = new Tile(mActivityInfo, "category");
+        final Tile tile = new ActivityTile(mActivityInfo, "category");
 
         assertThat(tile.getOrder()).isEqualTo(0);
     }
@@ -144,7 +143,7 @@
     public void getPriority_validMetadata_returnMetadataValue() {
         mActivityInfo.metaData.putInt(META_DATA_KEY_ORDER, 1);
 
-        final Tile tile = new Tile(mActivityInfo, "category");
+        final Tile tile = new ActivityTile(mActivityInfo, "category");
 
         assertThat(tile.getOrder()).isEqualTo(1);
     }
@@ -157,7 +156,7 @@
         spm.addResolveInfoForIntent(
                 new Intent().setClassName(mActivityInfo.packageName, mActivityInfo.name), info);
 
-        final Tile tile = new Tile(mActivityInfo, "category");
+        final Tile tile = new ActivityTile(mActivityInfo, "category");
         final long staleTimeStamp = -10000;
         tile.mLastUpdateTime = staleTimeStamp;
 
@@ -173,8 +172,8 @@
         final ShadowPackageManager spm = Shadow.extract(mContext.getPackageManager());
         spm.removePackage(mActivityInfo.packageName);
 
-        final Tile tile = new Tile(mActivityInfo, "category");
-        ReflectionHelpers.setField(tile, "mActivityInfo", null);
+        final Tile tile = new ActivityTile(mActivityInfo, "category");
+        tile.mComponentInfo = null;
 
         assertThat(tile.getTitle(RuntimeEnvironment.application)).isNull();
     }
diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/widget/AdaptiveIconTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/widget/AdaptiveIconTest.java
index ed6b9b0..6cbae05 100644
--- a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/widget/AdaptiveIconTest.java
+++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/widget/AdaptiveIconTest.java
@@ -37,6 +37,7 @@
 import android.os.Bundle;
 
 import com.android.settingslib.R;
+import com.android.settingslib.drawer.ActivityTile;
 import com.android.settingslib.drawer.CategoryKey;
 import com.android.settingslib.drawer.Tile;
 
@@ -84,7 +85,7 @@
 
     @Test
     public void setBackgroundColor_externalTileWithBackgroundColorRawValue_shouldUpdateIcon() {
-        final Tile tile = spy(new Tile(mActivityInfo, CategoryKey.CATEGORY_HOMEPAGE));
+        final Tile tile = spy(new ActivityTile(mActivityInfo, CategoryKey.CATEGORY_HOMEPAGE));
         mActivityInfo.metaData.putInt(META_DATA_PREFERENCE_ICON_BACKGROUND_ARGB, 0xff0000);
         doReturn(Icon.createWithResource(mContext, R.drawable.ic_system_update))
                 .when(tile).getIcon(mContext);
@@ -97,7 +98,7 @@
 
     @Test
     public void setBackgroundColor_tileWithoutBackgroundColor_shouldSetDefaultBackgroundColor() {
-        final Tile tile = spy(new Tile(mActivityInfo, CategoryKey.CATEGORY_HOMEPAGE));
+        final Tile tile = spy(new ActivityTile(mActivityInfo, CategoryKey.CATEGORY_HOMEPAGE));
         doReturn(Icon.createWithResource(mContext, R.drawable.ic_system_update))
             .when(tile).getIcon(mContext);
         final AdaptiveIcon icon = new AdaptiveIcon(mContext, new ColorDrawable(Color.BLACK));
@@ -110,7 +111,7 @@
 
     @Test
     public void onBindTile_externalTileWithBackgroundColorHint_shouldUpdateIcon() {
-        final Tile tile = spy(new Tile(mActivityInfo, CategoryKey.CATEGORY_HOMEPAGE));
+        final Tile tile = spy(new ActivityTile(mActivityInfo, CategoryKey.CATEGORY_HOMEPAGE));
         mActivityInfo.metaData.putInt(META_DATA_PREFERENCE_ICON_BACKGROUND_HINT,
                 R.color.bt_outline_color);
         doReturn(Icon.createWithResource(mContext, R.drawable.ic_system_update))
diff --git a/packages/SettingsProvider/src/android/provider/settings/backup/SecureSettings.java b/packages/SettingsProvider/src/android/provider/settings/backup/SecureSettings.java
index 8c2e431..8c97057 100644
--- a/packages/SettingsProvider/src/android/provider/settings/backup/SecureSettings.java
+++ b/packages/SettingsProvider/src/android/provider/settings/backup/SecureSettings.java
@@ -100,8 +100,6 @@
         Settings.Secure.DOZE_PICK_UP_GESTURE,
         Settings.Secure.DOZE_DOUBLE_TAP_GESTURE,
         Settings.Secure.DOZE_TAP_SCREEN_GESTURE,
-        Settings.Secure.DOZE_WAKE_LOCK_SCREEN_GESTURE,
-        Settings.Secure.DOZE_WAKE_DISPLAY_GESTURE,
         Settings.Secure.NFC_PAYMENT_DEFAULT_COMPONENT,
         Settings.Secure.AUTOMATIC_STORAGE_MANAGER_DAYS_TO_RETAIN,
         Settings.Secure.FACE_UNLOCK_KEYGUARD_ENABLED,
@@ -109,12 +107,8 @@
         Settings.Secure.FACE_UNLOCK_DISMISSES_KEYGUARD,
         Settings.Secure.FACE_UNLOCK_APP_ENABLED,
         Settings.Secure.FACE_UNLOCK_ALWAYS_REQUIRE_CONFIRMATION,
-        Settings.Secure.ASSIST_GESTURE_ENABLED,
-        Settings.Secure.ASSIST_GESTURE_SILENCE_ALERTS_ENABLED,
-        Settings.Secure.ASSIST_GESTURE_WAKE_ENABLED,
         Settings.Secure.VR_DISPLAY_MODE,
         Settings.Secure.NOTIFICATION_BADGING,
-        Settings.Secure.NOTIFICATION_BUBBLES,
         Settings.Secure.NOTIFICATION_DISMISS_RTL,
         Settings.Secure.QS_AUTO_ADDED_TILES,
         Settings.Secure.SCREENSAVER_ENABLED,
@@ -145,12 +139,9 @@
         Settings.Secure.TRUST_AGENTS_EXTEND_UNLOCK,
         Settings.Secure.UI_NIGHT_MODE,
         Settings.Secure.LOCK_SCREEN_WHEN_TRUST_LOST,
-        Settings.Secure.SKIP_GESTURE,
         Settings.Secure.SKIP_DIRECTION,
-        Settings.Secure.SILENCE_GESTURE,
         Settings.Secure.THEME_CUSTOMIZATION_OVERLAY_PACKAGES,
         Settings.Secure.NAVIGATION_MODE,
-        Settings.Secure.AWARE_ENABLED,
         Settings.Secure.SKIP_GESTURE_COUNT,
         Settings.Secure.SKIP_TOUCH_COUNT,
         Settings.Secure.SILENCE_ALARMS_GESTURE_COUNT,
diff --git a/packages/SettingsProvider/src/android/provider/settings/validators/SecureSettingsValidators.java b/packages/SettingsProvider/src/android/provider/settings/validators/SecureSettingsValidators.java
index f160edc6..976f336 100644
--- a/packages/SettingsProvider/src/android/provider/settings/validators/SecureSettingsValidators.java
+++ b/packages/SettingsProvider/src/android/provider/settings/validators/SecureSettingsValidators.java
@@ -157,7 +157,6 @@
         VALIDATORS.put(Secure.ASSIST_GESTURE_WAKE_ENABLED, BOOLEAN_VALIDATOR);
         VALIDATORS.put(Secure.VR_DISPLAY_MODE, new DiscreteValueValidator(new String[] {"0", "1"}));
         VALIDATORS.put(Secure.NOTIFICATION_BADGING, BOOLEAN_VALIDATOR);
-        VALIDATORS.put(Secure.NOTIFICATION_BUBBLES, BOOLEAN_VALIDATOR);
         VALIDATORS.put(Secure.NOTIFICATION_DISMISS_RTL, BOOLEAN_VALIDATOR);
         VALIDATORS.put(Secure.QS_AUTO_ADDED_TILES, TILE_LIST_VALIDATOR);
         VALIDATORS.put(Secure.SCREENSAVER_ENABLED, BOOLEAN_VALIDATOR);
diff --git a/packages/SettingsProvider/src/com/android/providers/settings/DeviceConfigService.java b/packages/SettingsProvider/src/com/android/providers/settings/DeviceConfigService.java
index d0ffe7a..8fb879d 100644
--- a/packages/SettingsProvider/src/com/android/providers/settings/DeviceConfigService.java
+++ b/packages/SettingsProvider/src/com/android/providers/settings/DeviceConfigService.java
@@ -16,7 +16,6 @@
 
 package com.android.providers.settings;
 
-import android.annotation.Nullable;
 import android.annotation.SystemApi;
 import android.app.ActivityManager;
 import android.content.IContentProvider;
@@ -195,8 +194,15 @@
                             : "Failed to delete " + key + " from " + namespace);
                     break;
                 case LIST:
-                    for (String line : list(iprovider, namespace)) {
-                        pout.println(line);
+                    if (namespace != null) {
+                        DeviceConfig.Properties properties = DeviceConfig.getProperties(namespace);
+                        for (String name : properties.getKeyset()) {
+                            pout.println(name + "=" + properties.getString(name, null));
+                        }
+                    } else {
+                        for (String line : listAll(iprovider)) {
+                            pout.println(line);
+                        }
                     }
                     break;
                 case RESET:
@@ -251,16 +257,13 @@
             return success;
         }
 
-        private List<String> list(IContentProvider provider, @Nullable String namespace) {
+        private List<String> listAll(IContentProvider provider) {
             final ArrayList<String> lines = new ArrayList<>();
 
             try {
                 Bundle args = new Bundle();
                 args.putInt(Settings.CALL_METHOD_USER_KEY,
                         ActivityManager.getService().getCurrentUser().id);
-                if (namespace != null) {
-                    args.putString(Settings.CALL_METHOD_PREFIX_KEY, namespace);
-                }
                 Bundle b = provider.call(resolveCallingPackage(), Settings.AUTHORITY,
                         Settings.CALL_METHOD_LIST_CONFIG, null, args);
                 if (b != null) {
diff --git a/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java b/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java
index 720266a..a9c466e 100644
--- a/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java
+++ b/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java
@@ -439,10 +439,8 @@
 
             case Settings.CALL_METHOD_LIST_CONFIG: {
                 String prefix = getSettingPrefix(args);
-                Bundle result = new Bundle();
-                result.putSerializable(
-                        Settings.NameValueTable.VALUE, (HashMap) getAllConfigFlags(prefix));
-                return result;
+                return packageValuesForCallResult(getAllConfigFlags(prefix),
+                        isTrackingGeneration(args));
             }
 
             case Settings.CALL_METHOD_LIST_GLOBAL: {
@@ -1076,7 +1074,7 @@
         return false;
     }
 
-    private Map<String, String> getAllConfigFlags(@Nullable String prefix) {
+    private HashMap<String, String> getAllConfigFlags(@Nullable String prefix) {
         if (DEBUG) {
             Slog.v(LOG_TAG, "getAllConfigFlags() for " + prefix);
         }
@@ -1085,12 +1083,11 @@
             // Get the settings.
             SettingsState settingsState = mSettingsRegistry.getSettingsLocked(
                     SETTINGS_TYPE_CONFIG, UserHandle.USER_SYSTEM);
-
             List<String> names = getSettingsNamesLocked(SETTINGS_TYPE_CONFIG,
                     UserHandle.USER_SYSTEM);
 
             final int nameCount = names.size();
-            Map<String, String> flagsToValues = new HashMap<>(names.size());
+            HashMap<String, String> flagsToValues = new HashMap<>(names.size());
 
             for (int i = 0; i < nameCount; i++) {
                 String name = names.get(i);
@@ -2057,8 +2054,7 @@
                 "get/set setting for user", null);
     }
 
-    private Bundle packageValueForCallResult(Setting setting,
-            boolean trackingGeneration) {
+    private Bundle packageValueForCallResult(Setting setting, boolean trackingGeneration) {
         if (!trackingGeneration) {
             if (setting == null || setting.isNull()) {
                 return NULL_SETTING_BUNDLE;
@@ -2073,6 +2069,21 @@
         return result;
     }
 
+    private Bundle packageValuesForCallResult(HashMap<String, String> keyValues,
+            boolean trackingGeneration) {
+        Bundle result = new Bundle();
+        result.putSerializable(Settings.NameValueTable.VALUE, keyValues);
+        if (trackingGeneration) {
+            synchronized (mLock) {
+                mSettingsRegistry.mGenerationRegistry.addGenerationData(result,
+                        mSettingsRegistry.getSettingsLocked(
+                                SETTINGS_TYPE_CONFIG, UserHandle.USER_SYSTEM).mKey);
+            }
+        }
+
+        return result;
+    }
+
     private static int getRequestingUserId(Bundle args) {
         final int callingUserId = UserHandle.getCallingUserId();
         return (args != null) ? args.getInt(Settings.CALL_METHOD_USER_KEY, callingUserId)
@@ -4385,8 +4396,7 @@
 
                 if (currentVersion == 182) {
                     // Remove secure bubble settings.
-                    getSecureSettingsLocked(userId).deleteSettingLocked(
-                            Secure.NOTIFICATION_BUBBLES);
+                    getSecureSettingsLocked(userId).deleteSettingLocked("notification_bubbles");
 
                     // Add global bubble settings.
                     getGlobalSettingsLocked().insertSettingLocked(Global.NOTIFICATION_BUBBLES,
diff --git a/packages/SettingsProvider/src/com/android/providers/settings/SettingsState.java b/packages/SettingsProvider/src/com/android/providers/settings/SettingsState.java
index c05c4cd..de6a3a8 100644
--- a/packages/SettingsProvider/src/com/android/providers/settings/SettingsState.java
+++ b/packages/SettingsProvider/src/com/android/providers/settings/SettingsState.java
@@ -24,7 +24,6 @@
 import android.content.pm.ApplicationInfo;
 import android.content.pm.PackageInfo;
 import android.content.pm.PackageManager;
-import android.content.pm.PackageManagerInternal;
 import android.content.pm.Signature;
 import android.os.Binder;
 import android.os.Build;
@@ -49,7 +48,6 @@
 
 import com.android.internal.annotations.GuardedBy;
 import com.android.internal.util.ArrayUtils;
-import com.android.server.LocalServices;
 
 import libcore.io.IoUtils;
 
@@ -1175,9 +1173,8 @@
                 }
 
                 // If SetupWizard, done.
-                PackageManagerInternal packageManagerInternal = LocalServices.getService(
-                        PackageManagerInternal.class);
-                if (packageName.equals(packageManagerInternal.getSetupWizardPackageName())) {
+                String setupWizPackage = context.getPackageManager().getSetupWizardPackageName();
+                if (packageName.equals(setupWizPackage)) {
                     sSystemUids.put(uid, uid);
                     return true;
                 }
diff --git a/packages/SettingsProvider/test/src/android/provider/SettingsBackupTest.java b/packages/SettingsProvider/test/src/android/provider/SettingsBackupTest.java
index 86625fa..8437eae 100644
--- a/packages/SettingsProvider/test/src/android/provider/SettingsBackupTest.java
+++ b/packages/SettingsProvider/test/src/android/provider/SettingsBackupTest.java
@@ -594,7 +594,10 @@
                  Settings.Secure.ANR_SHOW_BACKGROUND,
                  Settings.Secure.ASSISTANT,
                  Settings.Secure.ASSIST_DISCLOSURE_ENABLED,
+                 Settings.Secure.ASSIST_GESTURE_ENABLED,
                  Settings.Secure.ASSIST_GESTURE_SENSITIVITY,
+                 Settings.Secure.ASSIST_GESTURE_WAKE_ENABLED,
+                 Settings.Secure.ASSIST_GESTURE_SILENCE_ALERTS_ENABLED,
                  Settings.Secure.ASSIST_GESTURE_SETUP_COMPLETE,
                  Settings.Secure.ASSIST_SCREENSHOT_ENABLED,
                  Settings.Secure.ASSIST_STRUCTURE_ENABLED,
@@ -720,6 +723,11 @@
                  Settings.Secure.FACE_UNLOCK_ATTENTION_REQUIRED,
                  Settings.Secure.FACE_UNLOCK_DIVERSITY_REQUIRED,
                  Settings.Secure.MANAGED_PROVISIONING_DPC_DOWNLOADED,
+                 Settings.Secure.AWARE_ENABLED,
+                 Settings.Secure.SKIP_GESTURE,
+                 Settings.Secure.SILENCE_GESTURE,
+                 Settings.Secure.DOZE_WAKE_LOCK_SCREEN_GESTURE,
+                 Settings.Secure.DOZE_WAKE_DISPLAY_GESTURE,
                  Settings.Secure.FACE_UNLOCK_RE_ENROLL);
 
     @Test
diff --git a/packages/Shell/src/com/android/shell/BugreportProgressService.java b/packages/Shell/src/com/android/shell/BugreportProgressService.java
index 2a41aa6..665bde3 100644
--- a/packages/Shell/src/com/android/shell/BugreportProgressService.java
+++ b/packages/Shell/src/com/android/shell/BugreportProgressService.java
@@ -375,23 +375,27 @@
         }
     }
 
+    private static String getFileName(BugreportInfo info, String suffix) {
+        return String.format("%s-%s%s", info.baseName, info.name, suffix);
+    }
+
     private final class BugreportCallbackImpl extends BugreportCallback {
 
+        @GuardedBy("mLock")
         private final BugreportInfo mInfo;
 
-        BugreportCallbackImpl(String name, @Nullable String title, @Nullable String description,
-                @BugreportParams.BugreportMode int type) {
-            // pid not used in this workflow, so setting default = 0
-            mInfo = new BugreportInfo(mContext, 0 /* pid */, name,
-                    100 /* max progress*/, title, description, type);
+        BugreportCallbackImpl(BugreportInfo info) {
+            mInfo = info;
         }
 
         @Override
         public void onProgress(float progress) {
-            if (progress == 0) {
-                trackInfoWithId();
+            synchronized (mLock) {
+                if (progress == 0) {
+                    trackInfoWithIdLocked();
+                }
+                checkProgressUpdatedLocked(mInfo, (int) progress);
             }
-            checkProgressUpdated(mInfo, (int) progress);
         }
 
         /**
@@ -400,17 +404,21 @@
          */
         @Override
         public void onError(@BugreportErrorCode int errorCode) {
-            trackInfoWithId();
-            stopProgress(mInfo.id);
+            synchronized (mLock) {
+                trackInfoWithIdLocked();
+                stopProgressLocked(mInfo.id);
+            }
             Log.e(TAG, "Bugreport API callback onError() errorCode = " + errorCode);
             return;
         }
 
         @Override
         public void onFinished() {
-            // TODO: Make all callback functions lock protected.
-            trackInfoWithId();
-            sendBugreportFinishedBroadcast();
+            mInfo.renameBugreportFile();
+            mInfo.renameScreenshots(mScreenshotsDir);
+            synchronized (mLock) {
+                sendBugreportFinishedBroadcastLocked();
+            }
         }
 
         /**
@@ -419,7 +427,8 @@
          * when dumpstate calls one of the callback functions (onProgress, onFinished, onError)
          * after the id has been incremented.
          */
-        private void trackInfoWithId() {
+        @GuardedBy("mLock")
+        private void trackInfoWithIdLocked() {
             final int id = SystemProperties.getInt(PROPERTY_LAST_ID, 1);
             if (mBugreportInfos.get(id) == null) {
                 mInfo.id = id;
@@ -428,75 +437,75 @@
             return;
         }
 
-        private void sendBugreportFinishedBroadcast() {
-            final String bugreportFileName = mInfo.name + ".zip";
-            final File bugreportFile = new File(BUGREPORT_DIR, bugreportFileName);
-            final String bugreportFilePath = bugreportFile.getAbsolutePath();
-            if (bugreportFile.length() == 0) {
+        @GuardedBy("mLock")
+        private void sendBugreportFinishedBroadcastLocked() {
+            final String bugreportFilePath = mInfo.bugreportFile.getAbsolutePath();
+            if (mInfo.bugreportFile.length() == 0) {
                 Log.e(TAG, "Bugreport file empty. File path = " + bugreportFilePath);
                 return;
             }
             if (mInfo.type == BugreportParams.BUGREPORT_MODE_REMOTE) {
-                sendRemoteBugreportFinishedBroadcast(bugreportFilePath, bugreportFile);
+                sendRemoteBugreportFinishedBroadcast(mContext, bugreportFilePath,
+                        mInfo.bugreportFile);
             } else {
+                trackInfoWithIdLocked();
                 cleanupOldFiles(MIN_KEEP_COUNT, MIN_KEEP_AGE);
                 final Intent intent = new Intent(INTENT_BUGREPORT_FINISHED);
                 intent.putExtra(EXTRA_BUGREPORT, bugreportFilePath);
-                addScreenshotToIntent(intent);
+                addScreenshotToIntent(intent, mInfo);
                 mContext.sendBroadcast(intent, android.Manifest.permission.DUMP);
                 onBugreportFinished(mInfo.id);
             }
         }
+    }
 
-        private void sendRemoteBugreportFinishedBroadcast(String bugreportFileName,
-                File bugreportFile) {
-            cleanupOldFiles(REMOTE_BUGREPORT_FILES_AMOUNT, REMOTE_MIN_KEEP_AGE);
-            final Intent intent = new Intent(DevicePolicyManager.ACTION_REMOTE_BUGREPORT_DISPATCH);
-            final Uri bugreportUri = getUri(mContext, bugreportFile);
-            final String bugreportHash = generateFileHash(bugreportFileName);
-            if (bugreportHash == null) {
-                Log.e(TAG, "Error generating file hash for remote bugreport");
-                return;
-            }
-            intent.setDataAndType(bugreportUri, BUGREPORT_MIMETYPE);
-            intent.putExtra(DevicePolicyManager.EXTRA_REMOTE_BUGREPORT_HASH, bugreportHash);
-            intent.putExtra(EXTRA_BUGREPORT, bugreportFileName);
-            mContext.sendBroadcastAsUser(intent, UserHandle.SYSTEM,
-                    android.Manifest.permission.DUMP);
+    private static void sendRemoteBugreportFinishedBroadcast(Context context,
+            String bugreportFileName, File bugreportFile) {
+        cleanupOldFiles(REMOTE_BUGREPORT_FILES_AMOUNT, REMOTE_MIN_KEEP_AGE);
+        final Intent intent = new Intent(DevicePolicyManager.ACTION_REMOTE_BUGREPORT_DISPATCH);
+        final Uri bugreportUri = getUri(context, bugreportFile);
+        final String bugreportHash = generateFileHash(bugreportFileName);
+        if (bugreportHash == null) {
+            Log.e(TAG, "Error generating file hash for remote bugreport");
         }
+        intent.setDataAndType(bugreportUri, BUGREPORT_MIMETYPE);
+        intent.putExtra(DevicePolicyManager.EXTRA_REMOTE_BUGREPORT_HASH, bugreportHash);
+        intent.putExtra(EXTRA_BUGREPORT, bugreportFileName);
+        context.sendBroadcastAsUser(intent, UserHandle.SYSTEM,
+                android.Manifest.permission.DUMP);
+    }
 
-        private void addScreenshotToIntent(Intent intent) {
-            final String screenshotFileName = mInfo.name + ".png";
-            final File screenshotFile = new File(BUGREPORT_DIR, screenshotFileName);
+    private static void addScreenshotToIntent(Intent intent, BugreportInfo info) {
+        final File screenshotFile = info.screenshotFiles.isEmpty()
+                ? null : info.screenshotFiles.get(0);
+        if (screenshotFile != null && screenshotFile.length() > 0) {
             final String screenshotFilePath = screenshotFile.getAbsolutePath();
-            if (screenshotFile.length() > 0) {
-                intent.putExtra(EXTRA_SCREENSHOT, screenshotFilePath);
-            }
-            return;
+            intent.putExtra(EXTRA_SCREENSHOT, screenshotFilePath);
         }
+        return;
+    }
 
-        private String generateFileHash(String fileName) {
-            String fileHash = null;
-            try {
-                MessageDigest md = MessageDigest.getInstance("SHA-256");
-                FileInputStream input = new FileInputStream(new File(fileName));
-                byte[] buffer = new byte[65536];
-                int size;
-                while ((size = input.read(buffer)) > 0) {
-                    md.update(buffer, 0, size);
-                }
-                input.close();
-                byte[] hashBytes = md.digest();
-                StringBuilder sb = new StringBuilder();
-                for (int i = 0; i < hashBytes.length; i++) {
-                    sb.append(String.format("%02x", hashBytes[i]));
-                }
-                fileHash = sb.toString();
-            } catch (IOException | NoSuchAlgorithmException e) {
-                Log.e(TAG, "generating file hash for bugreport file failed " + fileName, e);
+    private static String generateFileHash(String fileName) {
+        String fileHash = null;
+        try {
+            MessageDigest md = MessageDigest.getInstance("SHA-256");
+            FileInputStream input = new FileInputStream(new File(fileName));
+            byte[] buffer = new byte[65536];
+            int size;
+            while ((size = input.read(buffer)) > 0) {
+                md.update(buffer, 0, size);
             }
-            return fileHash;
+            input.close();
+            byte[] hashBytes = md.digest();
+            StringBuilder sb = new StringBuilder();
+            for (int i = 0; i < hashBytes.length; i++) {
+                sb.append(String.format("%02x", hashBytes[i]));
+            }
+            fileHash = sb.toString();
+        } catch (IOException | NoSuchAlgorithmException e) {
+            Log.e(TAG, "generating file hash for bugreport file failed " + fileName, e);
         }
+        return fileHash;
     }
 
     static void cleanupOldFiles(final int minCount, final long minAge) {
@@ -670,34 +679,44 @@
         }
     }
 
-    private String getBugreportName() {
+    private String getBugreportBaseName(@BugreportParams.BugreportMode int type) {
         String buildId = SystemProperties.get("ro.build.id", "UNKNOWN_BUILD");
         String deviceName = SystemProperties.get("ro.product.name", "UNKNOWN_DEVICE");
-        String currentTimestamp = new SimpleDateFormat("yyyy-MM-dd-HH-mm-ss").format(new Date());
-        return String.format("bugreport-%s-%s-%s", deviceName, buildId, currentTimestamp);
+        String typeSuffix = null;
+        if (type == BugreportParams.BUGREPORT_MODE_WIFI) {
+            typeSuffix = "wifi";
+        } else if (type == BugreportParams.BUGREPORT_MODE_TELEPHONY) {
+            typeSuffix = "telephony";
+        } else {
+            return String.format("bugreport-%s-%s", deviceName, buildId);
+        }
+        return String.format("bugreport-%s-%s-%s", deviceName, buildId, typeSuffix);
     }
 
     private void startBugreportAPI(Intent intent) {
         mUsingBugreportApi = true;
-        String bugreportName = getBugreportName();
+        String shareTitle = intent.getStringExtra(EXTRA_TITLE);
+        String shareDescription = intent.getStringExtra(EXTRA_DESCRIPTION);
+        int bugreportType = intent.getIntExtra(EXTRA_BUGREPORT_TYPE,
+                BugreportParams.BUGREPORT_MODE_INTERACTIVE);
+        String baseName = getBugreportBaseName(bugreportType);
+        String name = new SimpleDateFormat("yyyy-MM-dd-HH-mm-ss").format(new Date());
 
-        ParcelFileDescriptor bugreportFd = createReadWriteFile(BUGREPORT_DIR,
-                bugreportName + ".zip");
+        // pid not used in this workflow, so setting default = 0
+        BugreportInfo info = new BugreportInfo(mContext, 0 /* pid */, baseName, name,
+                100 /* max progress*/, shareTitle, shareDescription, bugreportType,
+                mUsingBugreportApi);
+
+        ParcelFileDescriptor bugreportFd = info.createBugreportFd();
         if (bugreportFd == null) {
             Log.e(TAG, "Bugreport parcel file descriptor is null.");
             return;
         }
-        int bugreportType = intent.getIntExtra(EXTRA_BUGREPORT_TYPE,
-                BugreportParams.BUGREPORT_MODE_INTERACTIVE);
-        String shareTitle = intent.getStringExtra(EXTRA_TITLE);
-        String shareDescription = intent.getStringExtra(EXTRA_DESCRIPTION);
-
-        ParcelFileDescriptor screenshotFd = createReadWriteFile(BUGREPORT_DIR,
-                bugreportName + ".png");
+        ParcelFileDescriptor screenshotFd = info.createScreenshotFd();
         if (screenshotFd == null) {
             Log.e(TAG, "Screenshot parcel file descriptor is null. Deleting bugreport file");
             FileUtils.closeQuietly(bugreportFd);
-            new File(BUGREPORT_DIR, String.format("%s.zip", bugreportName)).delete();
+            info.bugreportFile.delete();
             return;
         }
         mBugreportManager = (BugreportManager) mContext.getSystemService(
@@ -708,8 +727,7 @@
                 + " bugreport file fd: " + bugreportFd
                 + " screenshot file fd: " + screenshotFd);
 
-        BugreportCallbackImpl bugreportCallback = new BugreportCallbackImpl(bugreportName,
-                shareTitle, shareDescription, bugreportType);
+        BugreportCallbackImpl bugreportCallback = new BugreportCallbackImpl(info);
         try {
             mBugreportManager.startBugreport(bugreportFd, screenshotFd,
                     new BugreportParams(bugreportType), executor, bugreportCallback);
@@ -722,14 +740,13 @@
         }
     }
 
-    private ParcelFileDescriptor createReadWriteFile(String dirName, String fileName) {
+    private static ParcelFileDescriptor createReadWriteFile(File file) {
         try {
-            File f = new File(dirName, fileName);
-            f.createNewFile();
-            f.setReadable(true, true);
-            f.setWritable(true, true);
+            file.createNewFile();
+            file.setReadable(true, true);
+            file.setWritable(true, true);
 
-            ParcelFileDescriptor fd = ParcelFileDescriptor.open(f,
+            ParcelFileDescriptor fd = ParcelFileDescriptor.open(file,
                     ParcelFileDescriptor.MODE_WRITE_ONLY | ParcelFileDescriptor.MODE_APPEND);
             return fd;
         } catch (IOException e) {
@@ -843,7 +860,8 @@
     /**
      * Finalizes the progress on a given bugreport and cancel its notification.
      */
-    private void stopProgress(int id) {
+    @GuardedBy("mLock")
+    private void stopProgressLocked(int id) {
         if (mBugreportInfos.indexOfKey(id) < 0) {
             Log.w(TAG, "ID not watched: " + id);
         } else {
@@ -874,7 +892,9 @@
             }
             deleteScreenshots(info);
         }
-        stopProgress(id);
+        synchronized (mLock) {
+            stopProgressLocked(id);
+        }
     }
 
     /**
@@ -1088,15 +1108,19 @@
      */
     private void onBugreportFinished(int id) {
         BugreportInfo info = getInfo(id);
-        final File bugreportFile = new File(BUGREPORT_DIR, info.name + ".zip");
+        final File bugreportFile = info.bugreportFile;
         final int max = -1; // this is to log metrics for dumpstate duration.
-        File screenshotFile = new File(BUGREPORT_DIR, info.name + ".png");
+        File screenshotFile = info.screenshotFiles.isEmpty()
+                ? null : info.screenshotFiles.get(0);
         // If the screenshot file did not get populated implies this type of bugreport does not
         // need the screenshot file; setting the file to null so that empty file doesnt get shared
-        if (screenshotFile.length() == 0) {
+        if (screenshotFile != null && screenshotFile.length() == 0) {
             if (screenshotFile.delete()) {
                 Log.d(TAG, "screenshot file deleted successfully.");
             }
+            info.screenshotFiles.remove(0);
+            // TODO(b/136066578): Will soon stop using the below variable as it is a no-op in
+            // API flow and the screenshotFile value is read from info.screenshotFiles
             screenshotFile = null;
         }
         // TODO: Since we are passing id to the function, it should be able to find the info linked
@@ -1120,10 +1144,18 @@
             DumpstateListener dumpstateListener = new DumpstateListener(info);
             mBugreportInfos.put(id, info);
         }
-        info.renameScreenshots(mScreenshotsDir);
-        info.bugreportFile = bugreportFile;
-        if (screenshotFile != null) {
-            info.addScreenshot(screenshotFile);
+        if (!mUsingBugreportApi) {
+            // Rename in API flow happens before sending the broadcast for remote bugreport (to
+            // handle renaming before sending broadcasts)
+            info.renameScreenshots(mScreenshotsDir);
+            // API workflow already has the bugreport file. This was required in legacy flow, when
+            // FINISHED broadcast would send the final bugreport files.
+            // TODO(b/136066578): Change function definition to not include bugreport/screenshot
+            // file in params
+            info.bugreportFile = bugreportFile;
+            if (screenshotFile != null) {
+                info.addScreenshot(screenshotFile);
+            }
         }
 
         if (max != -1) {
@@ -1157,7 +1189,9 @@
         if (!info.bugreportFile.exists() || !info.bugreportFile.canRead()) {
             Log.e(TAG, "Could not read bugreport file " + info.bugreportFile);
             Toast.makeText(context, R.string.bugreport_unreadable_text, Toast.LENGTH_LONG).show();
-            stopProgress(info.id);
+            synchronized (mLock) {
+                stopProgressLocked(info.id);
+            }
             return;
         }
 
@@ -1269,7 +1303,9 @@
         final Intent sendIntent = buildSendIntent(mContext, info);
         if (sendIntent == null) {
             Log.w(TAG, "Stopping progres on ID " + id + " because share intent could not be built");
-            stopProgress(id);
+            synchronized (mLock) {
+                stopProgressLocked(id);
+            }
             return;
         }
 
@@ -1292,9 +1328,10 @@
         } else {
             mContext.startActivity(notifIntent);
         }
-
-        // ... and stop watching this process.
-        stopProgress(id);
+        synchronized (mLock) {
+            // ... and stop watching this process.
+            stopProgressLocked(id);
+        }
     }
 
     static void sendShareIntent(Context context, Intent intent) {
@@ -1784,7 +1821,7 @@
                         if (hasFocus) {
                             return;
                         }
-                        sanitizeName();
+                        sanitizeName(info);
                     }
                 });
 
@@ -1803,9 +1840,13 @@
                                         MetricsLogger.action(context,
                                                 MetricsEvent.ACTION_BUGREPORT_DETAILS_CANCELED);
                                         if (!mTempName.equals(mSavedName)) {
-                                            // Must restore dumpstate's name since it was changed
+                                            // Must restore bugreport's name since it was changed
                                             // before user clicked OK.
-                                            setBugreportNameProperty(mPid, mSavedName);
+                                            if (mUsingBugreportApi) {
+                                                info.name = mSavedName;
+                                            } else {
+                                                setBugreportNameProperty(mPid, mSavedName);
+                                            }
                                         }
                                     }
                                 })
@@ -1854,7 +1895,7 @@
                     @Override
                     public void onClick(View view) {
                         MetricsLogger.action(context, MetricsEvent.ACTION_BUGREPORT_DETAILS_SAVED);
-                        sanitizeName();
+                        sanitizeName(info);
                         final String name = mInfoName.getText().toString();
                         final String title = mInfoTitle.getText().toString();
                         final String description = mInfoDescription.getText().toString();
@@ -1870,7 +1911,7 @@
          * Sanitizes the user-provided value for the {@code name} field, automatically replacing
          * invalid characters if necessary.
          */
-        private void sanitizeName() {
+        private void sanitizeName(BugreportInfo info) {
             String name = mInfoName.getText().toString();
             if (name.equals(mTempName)) {
                 if (DEBUG) Log.v(TAG, "name didn't change, no need to sanitize: " + name);
@@ -1892,23 +1933,15 @@
                 name = safeName.toString();
                 mInfoName.setText(name);
             }
-            if (mUsingBugreportApi) {
-                File prevFile = new File(BUGREPORT_DIR, mTempName + ".zip");
-                File newFile = new File(BUGREPORT_DIR, name + ".zip");
-                if (!prevFile.renameTo(newFile)) {
-                    Log.e(TAG, "File rename from : " + mTempName
-                            + " to : " + name + " from the UI failed.");
-                } else {
-                    Log.d(TAG, "File rename from : " + mTempName
-                            + " to : " + name + " from the UI succeeded.");
-                }
-            }
             mTempName = name;
-
-            // Must update system property for the cases where dumpstate finishes
-            // while the user is still entering other fields (like title or
-            // description)
-            setBugreportNameProperty(mPid, name);
+            if (mUsingBugreportApi) {
+                info.name = name;
+            } else {
+                // Must update system property for the cases where dumpstate finishes
+                // while the user is still entering other fields (like title or
+                // description)
+                setBugreportNameProperty(mPid, name);
+            }
         }
 
        /**
@@ -1944,14 +1977,23 @@
 
         /**
          * {@code pid} of the {@code dumpstate} process generating the bugreport.
+         * pid is unused in the API flow
+         * TODO(b/136066578): Remove pid
          */
         final int pid;
 
         /**
-         * Name of the bugreport, will be used to rename the final files.
-         * <p>
-         * Initial value is the bugreport filename reported by {@code dumpstate}, but user can
-         * change it later to a more meaningful name.
+         * Prefix name of the bugreport, this is uneditable.
+         * The baseName consists of the string "bugreport" + deviceName + buildID
+         * This will end with the string "wifi"/"telephony" for wifi/telephony bugreports.
+         * Bugreport zip file name  = "<baseName>-<name>.zip"
+         * Bugreport png file name = "<baseName>-<name>.png"
+         */
+        String baseName;
+
+        /**
+         * Suffix name of the bugreport/screenshot, is set to timestamp initially. User can make
+         * modifications to this using interface.
          */
         String name;
 
@@ -2021,6 +2063,12 @@
         boolean finished;
 
         /**
+         * Whether this bugreport is using API workflow.
+         * TODO(b/136066578): Remove when legacy bugreport methods are removed
+         */
+        boolean usingApi;
+
+        /**
          * Whether the details entries have been added to the bugreport yet.
          */
         boolean addingDetailsToZip;
@@ -2051,15 +2099,17 @@
             // onFinished() callback method is the only function where type is used.
             // Set type to -1 as it is unused in this workflow.
             // This constructor will soon be removed.
-            this(context, pid, name, max, null, null, -1);
+            this(context, pid, "" /* dumpstate handles basename */, name, max, null, null, -1,
+                    false);
             this.id = id;
         }
 
         /**
          * Constructor for tracked bugreports - typically called upon receiving BUGREPORT_REQUESTED.
          */
-        BugreportInfo(Context context, int pid, String name, int max, @Nullable String shareTitle,
-                @Nullable String shareDescription, int type) {
+        BugreportInfo(Context context, int pid, String baseName, String name, int max,
+                @Nullable String shareTitle, @Nullable String shareDescription,
+                @BugreportParams.BugreportMode int type, boolean usingApi) {
             this.context = context;
             this.pid = pid;
             this.name = name;
@@ -2067,6 +2117,8 @@
             this.shareTitle = shareTitle == null ? "" : shareTitle;
             this.shareDescription = shareDescription == null ? "" : shareDescription;
             this.type = type;
+            this.baseName = baseName;
+            this.usingApi = usingApi;
         }
 
         /**
@@ -2078,6 +2130,17 @@
             this.finished = true;
         }
 
+        ParcelFileDescriptor createBugreportFd() {
+            bugreportFile = new File(BUGREPORT_DIR, getFileName(this, ".zip"));
+            return createReadWriteFile(bugreportFile);
+        }
+
+        ParcelFileDescriptor createScreenshotFd() {
+            File screenshotFile = new File(BUGREPORT_DIR, getFileName(this, ".png"));
+            addScreenshot(screenshotFile);
+            return createReadWriteFile(screenshotFile);
+        }
+
         /**
          * Gets the name for next screenshot file.
          */
@@ -2103,7 +2166,12 @@
             final List<File> renamedFiles = new ArrayList<>(screenshotFiles.size());
             for (File oldFile : screenshotFiles) {
                 final String oldName = oldFile.getName();
-                final String newName = oldName.replaceFirst(Integer.toString(pid), name);
+                final String newName;
+                if (usingApi) {
+                    newName = getFileName(this, ".png");
+                } else {
+                    newName = oldName.replaceFirst(Integer.toString(pid), name);
+                }
                 final File newFile;
                 if (!newName.equals(oldName)) {
                     final File renamedFile = new File(screenshotDir, newName);
@@ -2118,6 +2186,18 @@
             screenshotFiles = renamedFiles;
         }
 
+        /**
+         * Rename bugreport file to include the name given by user via UI
+         */
+        void renameBugreportFile() {
+            File newBugreportFile = new File(BUGREPORT_DIR, getFileName(this, ".zip"));
+            if (!newBugreportFile.getPath().equals(bugreportFile.getPath())) {
+                if (bugreportFile.renameTo(newBugreportFile)) {
+                    bugreportFile = newBugreportFile;
+                }
+            }
+        }
+
         String getFormattedLastUpdate() {
             if (context == null) {
                 // Restored from Parcel
@@ -2136,8 +2216,10 @@
             final StringBuilder builder = new StringBuilder()
                     .append("\tid: ").append(id)
                     .append(", pid: ").append(pid)
+                    .append(", baseName: ").append(baseName)
                     .append(", name: ").append(name)
                     .append(", finished: ").append(finished)
+                    .append(", usingApi: ").append(usingApi)
                     .append("\n\ttitle: ").append(title)
                     .append("\n\tdescription: ");
             if (description == null) {
@@ -2169,6 +2251,7 @@
             context = null;
             id = in.readInt();
             pid = in.readInt();
+            baseName = in.readString();
             name = in.readString();
             title = in.readString();
             description = in.readString();
@@ -2186,6 +2269,7 @@
             }
 
             finished = in.readInt() == 1;
+            usingApi = in.readInt() == 1;
             screenshotCounter = in.readInt();
             shareDescription = in.readString();
             shareTitle = in.readString();
@@ -2195,6 +2279,7 @@
         public void writeToParcel(Parcel dest, int flags) {
             dest.writeInt(id);
             dest.writeInt(pid);
+            dest.writeString(baseName);
             dest.writeString(name);
             dest.writeString(title);
             dest.writeString(description);
@@ -2212,6 +2297,7 @@
             }
 
             dest.writeInt(finished ? 1 : 0);
+            dest.writeInt(usingApi ? 1 : 0);
             dest.writeInt(screenshotCounter);
             dest.writeString(shareDescription);
             dest.writeString(shareTitle);
@@ -2291,14 +2377,18 @@
                 // The right, long-term solution is to provide an onFinished() callback
                 // on IDumpstateListener and call it instead of using a broadcast.
                 Log.w(TAG, "Dumpstate process died:\n" + info);
-                stopProgress(info.id);
+                synchronized (mLock) {
+                    stopProgressLocked(info.id);
+                }
             }
             token.asBinder().unlinkToDeath(this, 0);
         }
 
         @Override
         public void onProgress(int progress) throws RemoteException {
-            checkProgressUpdated(info, progress);
+            synchronized (mLock) {
+                checkProgressUpdatedLocked(info, progress);
+            }
         }
 
         @Override
@@ -2317,7 +2407,8 @@
 
     }
 
-    private void checkProgressUpdated(BugreportInfo info, int progress) {
+    @GuardedBy("mLock")
+    private void checkProgressUpdatedLocked(BugreportInfo info, int progress) {
         if (progress > CAPPED_PROGRESS) {
             progress = CAPPED_PROGRESS;
         }
diff --git a/packages/SystemUI/AndroidManifest.xml b/packages/SystemUI/AndroidManifest.xml
index 403e894..b288eb7 100644
--- a/packages/SystemUI/AndroidManifest.xml
+++ b/packages/SystemUI/AndroidManifest.xml
@@ -243,6 +243,9 @@
     <!-- Permission to change the display color -->
     <uses-permission android:name="android.permission.CONTROL_DISPLAY_COLOR_TRANSFORMS" />
 
+    <!-- Query all packages on device on R+ -->
+    <uses-permission android:name="android.permission.QUERY_ALL_PACKAGES" />
+
     <protected-broadcast android:name="com.android.settingslib.action.REGISTER_SLICE_RECEIVER" />
     <protected-broadcast android:name="com.android.settingslib.action.UNREGISTER_SLICE_RECEIVER" />
     <protected-broadcast android:name="com.android.settings.flashlight.action.FLASHLIGHT_CHANGED" />
diff --git a/packages/SystemUI/README.md b/packages/SystemUI/README.md
index a8ce196..a3d420e 100644
--- a/packages/SystemUI/README.md
+++ b/packages/SystemUI/README.md
@@ -104,12 +104,6 @@
 Shows the drag handle for the divider between two apps when in split screen
 mode.
 
-### [com.android.systemui.SystemBars](/packages/SystemUI/src/com/android/systemui/SystemBars.java)
-
-This is a proxy to the actual SystemUI for the status bar. This loads from
-config_statusBarComponent which defaults to StatusBar. (maybe this should be
-removed and copy how config_systemUiVendorServiceComponent works)
-
 ### [com.android.systemui.status.phone.StatusBar](/packages/SystemUI/src/com/android/systemui/status/phone/StatusBar.java)
 
 This shows the UI for the status bar and the notification shade it contains.
diff --git a/packages/SystemUI/proguard.flags b/packages/SystemUI/proguard.flags
index 22b0ab7..3e74970 100644
--- a/packages/SystemUI/proguard.flags
+++ b/packages/SystemUI/proguard.flags
@@ -35,3 +35,7 @@
     *;
 }
 -keep class androidx.core.app.CoreComponentFactory
+
+-keep public class * extends com.android.systemui.SystemUI {
+    public <init>(android.content.Context);
+}
\ No newline at end of file
diff --git a/packages/SystemUI/res-keyguard/values-af/strings.xml b/packages/SystemUI/res-keyguard/values-af/strings.xml
index 11bcc88..b9122d2 100644
--- a/packages/SystemUI/res-keyguard/values-af/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-af/strings.xml
@@ -33,7 +33,7 @@
     <string name="keyguard_enter_your_password" msgid="5397328359341314506">"Voer jou wagwoord in"</string>
     <string name="keyguard_password_wrong_pin_code" msgid="6535018036285012028">"Verkeerde PIN-kode."</string>
     <string name="keyguard_sim_error_message_short" msgid="592109500618448312">"Ongeldige kaart."</string>
-    <string name="keyguard_charged" msgid="3316115607283493413">"Volgelaai"</string>
+    <string name="keyguard_charged" msgid="2222329688813033109">"Gelaai"</string>
     <string name="keyguard_plugged_in_wireless" msgid="8404159927155454732">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Laai tans draadloos"</string>
     <string name="keyguard_plugged_in" msgid="3161102098900158923">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Laai tans"</string>
     <string name="keyguard_plugged_in_charging_fast" msgid="3684592786276709342">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Laai tans vinnig"</string>
diff --git a/packages/SystemUI/res-keyguard/values-am/strings.xml b/packages/SystemUI/res-keyguard/values-am/strings.xml
index 4feb9f1..4cabaca 100644
--- a/packages/SystemUI/res-keyguard/values-am/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-am/strings.xml
@@ -33,7 +33,7 @@
     <string name="keyguard_enter_your_password" msgid="5397328359341314506">"ይለፍ ቃልዎን ያስገቡ"</string>
     <string name="keyguard_password_wrong_pin_code" msgid="6535018036285012028">"ትክክል ያልሆነ ፒን  ኮድ።"</string>
     <string name="keyguard_sim_error_message_short" msgid="592109500618448312">"ልክ ያልሆነ ካርድ።"</string>
-    <string name="keyguard_charged" msgid="3316115607283493413">"ሙሉ በሙሉ ኃይል ተሞልቷል"</string>
+    <string name="keyguard_charged" msgid="2222329688813033109">"ባትሪ ሞልቷል"</string>
     <string name="keyguard_plugged_in_wireless" msgid="8404159927155454732">"<xliff:g id="PERCENTAGE">%s</xliff:g> • በገመድ አልባ ኃይል በመሙላት ላይ"</string>
     <string name="keyguard_plugged_in" msgid="3161102098900158923">"<xliff:g id="PERCENTAGE">%s</xliff:g> • ኃይል በመሙላት ላይ"</string>
     <string name="keyguard_plugged_in_charging_fast" msgid="3684592786276709342">"<xliff:g id="PERCENTAGE">%s</xliff:g> • በፍጥነት ኃይልን በመሙላት ላይ"</string>
diff --git a/packages/SystemUI/res-keyguard/values-ar/strings.xml b/packages/SystemUI/res-keyguard/values-ar/strings.xml
index 4e163a2..d017953 100644
--- a/packages/SystemUI/res-keyguard/values-ar/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-ar/strings.xml
@@ -33,7 +33,7 @@
     <string name="keyguard_enter_your_password" msgid="5397328359341314506">"أدخل كلمة المرور"</string>
     <string name="keyguard_password_wrong_pin_code" msgid="6535018036285012028">"رمز رقم التعريف الشخصي غير صحيح."</string>
     <string name="keyguard_sim_error_message_short" msgid="592109500618448312">"بطاقة غير صالحة."</string>
-    <string name="keyguard_charged" msgid="3316115607283493413">"تم شحن البطارية بالكامل"</string>
+    <string name="keyguard_charged" msgid="2222329688813033109">"تم الشحن"</string>
     <string name="keyguard_plugged_in_wireless" msgid="8404159927155454732">"<xliff:g id="PERCENTAGE">%s</xliff:g> • جارٍ الشحن لاسلكيًا"</string>
     <string name="keyguard_plugged_in" msgid="3161102098900158923">"<xliff:g id="PERCENTAGE">%s</xliff:g> • جارٍ الشحن"</string>
     <string name="keyguard_plugged_in_charging_fast" msgid="3684592786276709342">"<xliff:g id="PERCENTAGE">%s</xliff:g> • جارٍ الشحن سريعًا"</string>
diff --git a/packages/SystemUI/res-keyguard/values-as/strings.xml b/packages/SystemUI/res-keyguard/values-as/strings.xml
index e225675..0c7dec3 100644
--- a/packages/SystemUI/res-keyguard/values-as/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-as/strings.xml
@@ -33,7 +33,7 @@
     <string name="keyguard_enter_your_password" msgid="5397328359341314506">"আপোনাৰ পাছৱর্ড দিয়ক"</string>
     <string name="keyguard_password_wrong_pin_code" msgid="6535018036285012028">"ভুল পিন ক\'ড।"</string>
     <string name="keyguard_sim_error_message_short" msgid="592109500618448312">"ব্যৱহাৰৰ অযোগ্য ছিম কাৰ্ড"</string>
-    <string name="keyguard_charged" msgid="3316115607283493413">"পূৰ্ণৰূপে চ্চাৰ্জ হৈছে"</string>
+    <string name="keyguard_charged" msgid="2222329688813033109">"চ্চার্জ কৰা হ’ল"</string>
     <string name="keyguard_plugged_in_wireless" msgid="8404159927155454732">"<xliff:g id="PERCENTAGE">%s</xliff:g> • বেতাঁৰৰ জৰিয়তে চাৰ্জ কৰি থকা হৈছে"</string>
     <string name="keyguard_plugged_in" msgid="3161102098900158923">"<xliff:g id="PERCENTAGE">%s</xliff:g> • চ্চার্জ কৰি থকা হৈছে"</string>
     <string name="keyguard_plugged_in_charging_fast" msgid="3684592786276709342">"<xliff:g id="PERCENTAGE">%s</xliff:g> • দ্ৰুত গতিৰে চ্চাৰ্জ কৰি থকা হৈছে"</string>
diff --git a/packages/SystemUI/res-keyguard/values-az/strings.xml b/packages/SystemUI/res-keyguard/values-az/strings.xml
index c0cf129..8cdf2f0 100644
--- a/packages/SystemUI/res-keyguard/values-az/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-az/strings.xml
@@ -33,7 +33,7 @@
     <string name="keyguard_enter_your_password" msgid="5397328359341314506">"Şifrənizi daxil edin"</string>
     <string name="keyguard_password_wrong_pin_code" msgid="6535018036285012028">"Yanlış PIN kod."</string>
     <string name="keyguard_sim_error_message_short" msgid="592109500618448312">"Yanlış Kart."</string>
-    <string name="keyguard_charged" msgid="3316115607283493413">"Tam dolub"</string>
+    <string name="keyguard_charged" msgid="2222329688813033109">"Enerji yığdı"</string>
     <string name="keyguard_plugged_in_wireless" msgid="8404159927155454732">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Simsiz şəkildə batareya yığır"</string>
     <string name="keyguard_plugged_in" msgid="3161102098900158923">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Enerji yığır"</string>
     <string name="keyguard_plugged_in_charging_fast" msgid="3684592786276709342">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Sürətlə enerji yığır"</string>
diff --git a/packages/SystemUI/res-keyguard/values-b+sr+Latn/strings.xml b/packages/SystemUI/res-keyguard/values-b+sr+Latn/strings.xml
index 88ca77b..eeda7ce 100644
--- a/packages/SystemUI/res-keyguard/values-b+sr+Latn/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-b+sr+Latn/strings.xml
@@ -33,7 +33,7 @@
     <string name="keyguard_enter_your_password" msgid="5397328359341314506">"Unesite lozinku"</string>
     <string name="keyguard_password_wrong_pin_code" msgid="6535018036285012028">"PIN kôd je netačan."</string>
     <string name="keyguard_sim_error_message_short" msgid="592109500618448312">"Nevažeća kartica."</string>
-    <string name="keyguard_charged" msgid="3316115607283493413">"Napunjena je u potpunosti"</string>
+    <string name="keyguard_charged" msgid="2222329688813033109">"Napunjena je"</string>
     <string name="keyguard_plugged_in_wireless" msgid="8404159927155454732">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Bežično punjenje"</string>
     <string name="keyguard_plugged_in" msgid="3161102098900158923">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Puni se"</string>
     <string name="keyguard_plugged_in_charging_fast" msgid="3684592786276709342">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Brzo se puni"</string>
diff --git a/packages/SystemUI/res-keyguard/values-be/strings.xml b/packages/SystemUI/res-keyguard/values-be/strings.xml
index a897fb2..09cda6b 100644
--- a/packages/SystemUI/res-keyguard/values-be/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-be/strings.xml
@@ -33,7 +33,7 @@
     <string name="keyguard_enter_your_password" msgid="5397328359341314506">"Увядзіце пароль"</string>
     <string name="keyguard_password_wrong_pin_code" msgid="6535018036285012028">"Няправільны PIN-код."</string>
     <string name="keyguard_sim_error_message_short" msgid="592109500618448312">"Несапраўдная картка."</string>
-    <string name="keyguard_charged" msgid="3316115607283493413">"Акумулятар поўнасцю зараджаны"</string>
+    <string name="keyguard_charged" msgid="2222329688813033109">"Зараджаны"</string>
     <string name="keyguard_plugged_in_wireless" msgid="8404159927155454732">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Ідзе бесправадная зарадка"</string>
     <string name="keyguard_plugged_in" msgid="3161102098900158923">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Ідзе зарадка"</string>
     <string name="keyguard_plugged_in_charging_fast" msgid="3684592786276709342">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Ідзе хуткая зарадка"</string>
diff --git a/packages/SystemUI/res-keyguard/values-bg/strings.xml b/packages/SystemUI/res-keyguard/values-bg/strings.xml
index eebdb9e..75942ea 100644
--- a/packages/SystemUI/res-keyguard/values-bg/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-bg/strings.xml
@@ -33,7 +33,7 @@
     <string name="keyguard_enter_your_password" msgid="5397328359341314506">"Въведете паролата си"</string>
     <string name="keyguard_password_wrong_pin_code" msgid="6535018036285012028">"Неправилен ПИН код."</string>
     <string name="keyguard_sim_error_message_short" msgid="592109500618448312">"Картата е невалидна."</string>
-    <string name="keyguard_charged" msgid="3316115607283493413">"Напълно заредено"</string>
+    <string name="keyguard_charged" msgid="2222329688813033109">"Заредена"</string>
     <string name="keyguard_plugged_in_wireless" msgid="8404159927155454732">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Зарежда се безжично"</string>
     <string name="keyguard_plugged_in" msgid="3161102098900158923">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Зарежда се"</string>
     <string name="keyguard_plugged_in_charging_fast" msgid="3684592786276709342">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Зарежда се бързо"</string>
diff --git a/packages/SystemUI/res-keyguard/values-bn/strings.xml b/packages/SystemUI/res-keyguard/values-bn/strings.xml
index b544c14..0e8189f 100644
--- a/packages/SystemUI/res-keyguard/values-bn/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-bn/strings.xml
@@ -33,7 +33,7 @@
     <string name="keyguard_enter_your_password" msgid="5397328359341314506">"পাসওয়ার্ড লিখুন"</string>
     <string name="keyguard_password_wrong_pin_code" msgid="6535018036285012028">"ভুল পিন কোড দেওয়া হয়েছে।"</string>
     <string name="keyguard_sim_error_message_short" msgid="592109500618448312">"ভুল কার্ড।"</string>
-    <string name="keyguard_charged" msgid="3316115607283493413">"সম্পূর্ণ চার্জ আছে"</string>
+    <string name="keyguard_charged" msgid="2222329688813033109">"চার্জ হয়েছে"</string>
     <string name="keyguard_plugged_in_wireless" msgid="8404159927155454732">"<xliff:g id="PERCENTAGE">%s</xliff:g> • ওয়্যারলেস পদ্ধতিতে চার্জ হচ্ছে"</string>
     <string name="keyguard_plugged_in" msgid="3161102098900158923">"<xliff:g id="PERCENTAGE">%s</xliff:g> • চার্জ হচ্ছে"</string>
     <string name="keyguard_plugged_in_charging_fast" msgid="3684592786276709342">"<xliff:g id="PERCENTAGE">%s</xliff:g> • দ্রুত চার্জ হচ্ছে"</string>
diff --git a/packages/SystemUI/res-keyguard/values-bs/strings.xml b/packages/SystemUI/res-keyguard/values-bs/strings.xml
index 8547bc8..33fe43f 100644
--- a/packages/SystemUI/res-keyguard/values-bs/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-bs/strings.xml
@@ -33,7 +33,7 @@
     <string name="keyguard_enter_your_password" msgid="5397328359341314506">"Unesite lozinku"</string>
     <string name="keyguard_password_wrong_pin_code" msgid="6535018036285012028">"Pogrešan PIN."</string>
     <string name="keyguard_sim_error_message_short" msgid="592109500618448312">"Nevažeća kartica."</string>
-    <string name="keyguard_charged" msgid="3316115607283493413">"Potpuno napunjen"</string>
+    <string name="keyguard_charged" msgid="2222329688813033109">"Napunjeno"</string>
     <string name="keyguard_plugged_in_wireless" msgid="8404159927155454732">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Bežično punjenje"</string>
     <string name="keyguard_plugged_in" msgid="3161102098900158923">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Punjenje"</string>
     <string name="keyguard_plugged_in_charging_fast" msgid="3684592786276709342">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Brzo punjenje"</string>
diff --git a/packages/SystemUI/res-keyguard/values-ca/strings.xml b/packages/SystemUI/res-keyguard/values-ca/strings.xml
index ccde138..6c85fd3 100644
--- a/packages/SystemUI/res-keyguard/values-ca/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-ca/strings.xml
@@ -33,7 +33,7 @@
     <string name="keyguard_enter_your_password" msgid="5397328359341314506">"Introdueix la contrasenya"</string>
     <string name="keyguard_password_wrong_pin_code" msgid="6535018036285012028">"El codi PIN no és correcte."</string>
     <string name="keyguard_sim_error_message_short" msgid="592109500618448312">"La targeta no és vàlida."</string>
-    <string name="keyguard_charged" msgid="3316115607283493413">"Completament carregada"</string>
+    <string name="keyguard_charged" msgid="2222329688813033109">"Bateria carregada"</string>
     <string name="keyguard_plugged_in_wireless" msgid="8404159927155454732">"<xliff:g id="PERCENTAGE">%s</xliff:g> • S\'està carregant sense fil"</string>
     <string name="keyguard_plugged_in" msgid="3161102098900158923">"<xliff:g id="PERCENTAGE">%s</xliff:g> • S\'està carregant"</string>
     <string name="keyguard_plugged_in_charging_fast" msgid="3684592786276709342">"<xliff:g id="PERCENTAGE">%s</xliff:g> • S\'està carregant ràpidament"</string>
diff --git a/packages/SystemUI/res-keyguard/values-cs/strings.xml b/packages/SystemUI/res-keyguard/values-cs/strings.xml
index 3adc279..e944312 100644
--- a/packages/SystemUI/res-keyguard/values-cs/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-cs/strings.xml
@@ -33,7 +33,7 @@
     <string name="keyguard_enter_your_password" msgid="5397328359341314506">"Zadejte heslo"</string>
     <string name="keyguard_password_wrong_pin_code" msgid="6535018036285012028">"Nesprávný kód PIN."</string>
     <string name="keyguard_sim_error_message_short" msgid="592109500618448312">"Neplatná karta."</string>
-    <string name="keyguard_charged" msgid="3316115607283493413">"Plně nabito"</string>
+    <string name="keyguard_charged" msgid="2222329688813033109">"Nabito"</string>
     <string name="keyguard_plugged_in_wireless" msgid="8404159927155454732">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Bezdrátové nabíjení"</string>
     <string name="keyguard_plugged_in" msgid="3161102098900158923">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Nabíjení"</string>
     <string name="keyguard_plugged_in_charging_fast" msgid="3684592786276709342">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Rychlé nabíjení"</string>
diff --git a/packages/SystemUI/res-keyguard/values-da/strings.xml b/packages/SystemUI/res-keyguard/values-da/strings.xml
index 0e6a1f3..ac1791b 100644
--- a/packages/SystemUI/res-keyguard/values-da/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-da/strings.xml
@@ -33,7 +33,7 @@
     <string name="keyguard_enter_your_password" msgid="5397328359341314506">"Angiv din adgangskode"</string>
     <string name="keyguard_password_wrong_pin_code" msgid="6535018036285012028">"Forkert pinkode."</string>
     <string name="keyguard_sim_error_message_short" msgid="592109500618448312">"Ugyldigt kort."</string>
-    <string name="keyguard_charged" msgid="3316115607283493413">"Fuldt opladet"</string>
+    <string name="keyguard_charged" msgid="2222329688813033109">"Opladet"</string>
     <string name="keyguard_plugged_in_wireless" msgid="8404159927155454732">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Trådløs opladning"</string>
     <string name="keyguard_plugged_in" msgid="3161102098900158923">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Oplader"</string>
     <string name="keyguard_plugged_in_charging_fast" msgid="3684592786276709342">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Oplader hurtigt"</string>
diff --git a/packages/SystemUI/res-keyguard/values-de/strings.xml b/packages/SystemUI/res-keyguard/values-de/strings.xml
index d44bfbc..0607c8a 100644
--- a/packages/SystemUI/res-keyguard/values-de/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-de/strings.xml
@@ -33,7 +33,7 @@
     <string name="keyguard_enter_your_password" msgid="5397328359341314506">"Passwort eingeben"</string>
     <string name="keyguard_password_wrong_pin_code" msgid="6535018036285012028">"Falscher PIN-Code."</string>
     <string name="keyguard_sim_error_message_short" msgid="592109500618448312">"Ungültige Karte."</string>
-    <string name="keyguard_charged" msgid="3316115607283493413">"Vollständig aufgeladen"</string>
+    <string name="keyguard_charged" msgid="2222329688813033109">"Aufgeladen"</string>
     <string name="keyguard_plugged_in_wireless" msgid="8404159927155454732">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Kabelloses Laden"</string>
     <string name="keyguard_plugged_in" msgid="3161102098900158923">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Wird geladen"</string>
     <string name="keyguard_plugged_in_charging_fast" msgid="3684592786276709342">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Wird schnell geladen"</string>
diff --git a/packages/SystemUI/res-keyguard/values-el/strings.xml b/packages/SystemUI/res-keyguard/values-el/strings.xml
index 46b1d30..6997b16 100644
--- a/packages/SystemUI/res-keyguard/values-el/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-el/strings.xml
@@ -33,7 +33,7 @@
     <string name="keyguard_enter_your_password" msgid="5397328359341314506">"Εισαγάγετε κωδικό πρόσβασης"</string>
     <string name="keyguard_password_wrong_pin_code" msgid="6535018036285012028">"Λανθασμένος κωδικός PIN."</string>
     <string name="keyguard_sim_error_message_short" msgid="592109500618448312">"Μη έγκυρη κάρτα."</string>
-    <string name="keyguard_charged" msgid="3316115607283493413">"Πλήρως φορτισμένη"</string>
+    <string name="keyguard_charged" msgid="2222329688813033109">"Φορτίστηκε"</string>
     <string name="keyguard_plugged_in_wireless" msgid="8404159927155454732">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Ασύρματη φόρτιση"</string>
     <string name="keyguard_plugged_in" msgid="3161102098900158923">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Φόρτιση"</string>
     <string name="keyguard_plugged_in_charging_fast" msgid="3684592786276709342">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Γρήγορη φόρτιση"</string>
diff --git a/packages/SystemUI/res-keyguard/values-en-rAU/strings.xml b/packages/SystemUI/res-keyguard/values-en-rAU/strings.xml
index 5640b6d..19dd191 100644
--- a/packages/SystemUI/res-keyguard/values-en-rAU/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-en-rAU/strings.xml
@@ -33,7 +33,7 @@
     <string name="keyguard_enter_your_password" msgid="5397328359341314506">"Enter your password"</string>
     <string name="keyguard_password_wrong_pin_code" msgid="6535018036285012028">"Incorrect PIN code."</string>
     <string name="keyguard_sim_error_message_short" msgid="592109500618448312">"Invalid card."</string>
-    <string name="keyguard_charged" msgid="3316115607283493413">"Fully charged"</string>
+    <string name="keyguard_charged" msgid="2222329688813033109">"Charged"</string>
     <string name="keyguard_plugged_in_wireless" msgid="8404159927155454732">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Charging wirelessly"</string>
     <string name="keyguard_plugged_in" msgid="3161102098900158923">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Charging"</string>
     <string name="keyguard_plugged_in_charging_fast" msgid="3684592786276709342">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Charging rapidly"</string>
diff --git a/packages/SystemUI/res-keyguard/values-en-rCA/strings.xml b/packages/SystemUI/res-keyguard/values-en-rCA/strings.xml
index 5836b72..acfb7e2 100644
--- a/packages/SystemUI/res-keyguard/values-en-rCA/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-en-rCA/strings.xml
@@ -33,7 +33,7 @@
     <string name="keyguard_enter_your_password" msgid="5397328359341314506">"Enter your password"</string>
     <string name="keyguard_password_wrong_pin_code" msgid="6535018036285012028">"Incorrect PIN code."</string>
     <string name="keyguard_sim_error_message_short" msgid="592109500618448312">"Invalid card."</string>
-    <string name="keyguard_charged" msgid="3316115607283493413">"Fully charged"</string>
+    <string name="keyguard_charged" msgid="2222329688813033109">"Charged"</string>
     <string name="keyguard_plugged_in_wireless" msgid="8404159927155454732">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Charging wirelessly"</string>
     <string name="keyguard_plugged_in" msgid="3161102098900158923">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Charging"</string>
     <string name="keyguard_plugged_in_charging_fast" msgid="3684592786276709342">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Charging rapidly"</string>
diff --git a/packages/SystemUI/res-keyguard/values-en-rGB/strings.xml b/packages/SystemUI/res-keyguard/values-en-rGB/strings.xml
index 5640b6d..19dd191 100644
--- a/packages/SystemUI/res-keyguard/values-en-rGB/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-en-rGB/strings.xml
@@ -33,7 +33,7 @@
     <string name="keyguard_enter_your_password" msgid="5397328359341314506">"Enter your password"</string>
     <string name="keyguard_password_wrong_pin_code" msgid="6535018036285012028">"Incorrect PIN code."</string>
     <string name="keyguard_sim_error_message_short" msgid="592109500618448312">"Invalid card."</string>
-    <string name="keyguard_charged" msgid="3316115607283493413">"Fully charged"</string>
+    <string name="keyguard_charged" msgid="2222329688813033109">"Charged"</string>
     <string name="keyguard_plugged_in_wireless" msgid="8404159927155454732">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Charging wirelessly"</string>
     <string name="keyguard_plugged_in" msgid="3161102098900158923">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Charging"</string>
     <string name="keyguard_plugged_in_charging_fast" msgid="3684592786276709342">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Charging rapidly"</string>
diff --git a/packages/SystemUI/res-keyguard/values-en-rIN/strings.xml b/packages/SystemUI/res-keyguard/values-en-rIN/strings.xml
index 5640b6d..19dd191 100644
--- a/packages/SystemUI/res-keyguard/values-en-rIN/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-en-rIN/strings.xml
@@ -33,7 +33,7 @@
     <string name="keyguard_enter_your_password" msgid="5397328359341314506">"Enter your password"</string>
     <string name="keyguard_password_wrong_pin_code" msgid="6535018036285012028">"Incorrect PIN code."</string>
     <string name="keyguard_sim_error_message_short" msgid="592109500618448312">"Invalid card."</string>
-    <string name="keyguard_charged" msgid="3316115607283493413">"Fully charged"</string>
+    <string name="keyguard_charged" msgid="2222329688813033109">"Charged"</string>
     <string name="keyguard_plugged_in_wireless" msgid="8404159927155454732">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Charging wirelessly"</string>
     <string name="keyguard_plugged_in" msgid="3161102098900158923">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Charging"</string>
     <string name="keyguard_plugged_in_charging_fast" msgid="3684592786276709342">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Charging rapidly"</string>
diff --git a/packages/SystemUI/res-keyguard/values-en-rXC/strings.xml b/packages/SystemUI/res-keyguard/values-en-rXC/strings.xml
index fb968b7..b29bd60 100644
--- a/packages/SystemUI/res-keyguard/values-en-rXC/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-en-rXC/strings.xml
@@ -33,7 +33,7 @@
     <string name="keyguard_enter_your_password" msgid="5397328359341314506">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‎‏‎‏‎‏‏‏‎‎‏‏‏‎‎‏‎‏‎‎‏‏‎‎‎‏‎‏‏‏‏‏‎‏‎‏‎‏‎‏‎‏‏‏‎‎‏‎‏‎‎‎‏‏‏‎‎‏‎‏‎‎Enter your password‎‏‎‎‏‎"</string>
     <string name="keyguard_password_wrong_pin_code" msgid="6535018036285012028">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‏‏‎‏‎‏‎‏‏‎‎‎‏‎‎‎‎‏‏‎‎‎‏‎‎‎‏‏‏‏‎‏‎‏‏‎‏‏‎‎‎‏‎‎‏‏‏‏‏‏‎‎‎‎‎‏‏‏‏‎‎‎Incorrect PIN code.‎‏‎‎‏‎"</string>
     <string name="keyguard_sim_error_message_short" msgid="592109500618448312">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‎‎‏‎‎‎‎‎‏‏‎‏‏‏‏‎‎‏‏‎‎‎‎‏‏‏‎‏‎‎‎‎‏‎‎‏‎‎‎‏‏‏‏‏‏‏‎‎‎‏‏‏‎‏‏‎‏‏‏‎‎‎‎Invalid Card.‎‏‎‎‏‎"</string>
-    <string name="keyguard_charged" msgid="3316115607283493413">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‎‏‏‏‎‎‎‎‎‎‏‎‏‎‎‏‏‎‏‎‏‏‎‎‏‎‎‏‏‎‏‎‎‎‏‏‎‎‏‎‎‎‎‏‎‏‏‏‎‏‎‏‎‎‎‏‎‎‏‎‏‎Fully charged‎‏‎‎‏‎"</string>
+    <string name="keyguard_charged" msgid="2222329688813033109">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‎‏‏‏‏‏‎‏‏‎‏‎‏‏‏‎‏‎‎‏‏‎‏‎‎‎‏‎‎‏‏‏‏‎‏‏‎‏‏‏‎‎‎‎‎‎‏‎‏‎‏‎‏‏‎‏‎‎‏‎‏‎‏‎Charged‎‏‎‎‏‎"</string>
     <string name="keyguard_plugged_in_wireless" msgid="8404159927155454732">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‏‎‏‎‎‏‎‏‎‎‎‎‏‏‎‎‏‎‎‏‎‏‏‏‎‏‏‎‏‎‎‏‏‎‏‎‏‏‎‏‎‏‏‎‎‎‏‏‏‎‎‏‏‎‎‎‎‏‏‎‎‎‎‏‎‎‏‏‎<xliff:g id="PERCENTAGE">%s</xliff:g>‎‏‎‎‏‏‏‎ • Charging wirelessly‎‏‎‎‏‎"</string>
     <string name="keyguard_plugged_in" msgid="3161102098900158923">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‎‏‎‏‏‏‏‎‏‏‏‏‎‎‏‏‏‏‏‎‏‏‎‎‏‏‏‎‎‎‏‎‏‎‏‏‏‏‎‏‎‏‏‏‏‏‎‎‎‏‎‎‏‏‏‎‎‏‎‏‏‎‎‏‎‎‏‏‎<xliff:g id="PERCENTAGE">%s</xliff:g>‎‏‎‎‏‏‏‎ • Charging‎‏‎‎‏‎"</string>
     <string name="keyguard_plugged_in_charging_fast" msgid="3684592786276709342">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‏‎‎‏‏‎‎‏‎‎‎‏‎‎‏‎‎‏‏‎‏‏‎‎‏‏‏‏‎‎‎‎‎‎‏‏‏‏‏‏‏‏‏‎‏‎‏‏‏‎‎‏‏‏‏‎‏‏‏‏‎‎‎‏‎‎‏‏‎<xliff:g id="PERCENTAGE">%s</xliff:g>‎‏‎‎‏‏‏‎ • Charging rapidly‎‏‎‎‏‎"</string>
diff --git a/packages/SystemUI/res-keyguard/values-es-rUS/strings.xml b/packages/SystemUI/res-keyguard/values-es-rUS/strings.xml
index 727cbad..aa5c4e0 100644
--- a/packages/SystemUI/res-keyguard/values-es-rUS/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-es-rUS/strings.xml
@@ -33,7 +33,7 @@
     <string name="keyguard_enter_your_password" msgid="5397328359341314506">"Ingresa tu contraseña"</string>
     <string name="keyguard_password_wrong_pin_code" msgid="6535018036285012028">"Código PIN incorrecto"</string>
     <string name="keyguard_sim_error_message_short" msgid="592109500618448312">"Tarjeta no válida"</string>
-    <string name="keyguard_charged" msgid="3316115607283493413">"Carga completa"</string>
+    <string name="keyguard_charged" msgid="2222329688813033109">"Cargada"</string>
     <string name="keyguard_plugged_in_wireless" msgid="8404159927155454732">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Cargando de manera inalámbrica"</string>
     <string name="keyguard_plugged_in" msgid="3161102098900158923">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Cargando"</string>
     <string name="keyguard_plugged_in_charging_fast" msgid="3684592786276709342">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Cargando rápidamente"</string>
diff --git a/packages/SystemUI/res-keyguard/values-es/strings.xml b/packages/SystemUI/res-keyguard/values-es/strings.xml
index 870741e..5f9a456 100644
--- a/packages/SystemUI/res-keyguard/values-es/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-es/strings.xml
@@ -33,7 +33,7 @@
     <string name="keyguard_enter_your_password" msgid="5397328359341314506">"Introduce tu contraseña"</string>
     <string name="keyguard_password_wrong_pin_code" msgid="6535018036285012028">"El código PIN es incorrecto."</string>
     <string name="keyguard_sim_error_message_short" msgid="592109500618448312">"Tarjeta no válida."</string>
-    <string name="keyguard_charged" msgid="3316115607283493413">"Carga completa"</string>
+    <string name="keyguard_charged" msgid="2222329688813033109">"Cargada"</string>
     <string name="keyguard_plugged_in_wireless" msgid="8404159927155454732">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Cargando sin cables"</string>
     <string name="keyguard_plugged_in" msgid="3161102098900158923">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Cargando"</string>
     <string name="keyguard_plugged_in_charging_fast" msgid="3684592786276709342">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Cargando rápidamente"</string>
diff --git a/packages/SystemUI/res-keyguard/values-et/strings.xml b/packages/SystemUI/res-keyguard/values-et/strings.xml
index b6cac13..c555ced 100644
--- a/packages/SystemUI/res-keyguard/values-et/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-et/strings.xml
@@ -33,7 +33,7 @@
     <string name="keyguard_enter_your_password" msgid="5397328359341314506">"Sisestage parool"</string>
     <string name="keyguard_password_wrong_pin_code" msgid="6535018036285012028">"Vale PIN-kood."</string>
     <string name="keyguard_sim_error_message_short" msgid="592109500618448312">"Kehtetu kaart."</string>
-    <string name="keyguard_charged" msgid="3316115607283493413">"Täielikult laetud"</string>
+    <string name="keyguard_charged" msgid="2222329688813033109">"Laetud"</string>
     <string name="keyguard_plugged_in_wireless" msgid="8404159927155454732">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Juhtmeta laadimine"</string>
     <string name="keyguard_plugged_in" msgid="3161102098900158923">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Laadimine"</string>
     <string name="keyguard_plugged_in_charging_fast" msgid="3684592786276709342">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Kiirlaadimine"</string>
diff --git a/packages/SystemUI/res-keyguard/values-eu/strings.xml b/packages/SystemUI/res-keyguard/values-eu/strings.xml
index 8ad942b..612b2de 100644
--- a/packages/SystemUI/res-keyguard/values-eu/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-eu/strings.xml
@@ -33,7 +33,7 @@
     <string name="keyguard_enter_your_password" msgid="5397328359341314506">"Idatzi pasahitza"</string>
     <string name="keyguard_password_wrong_pin_code" msgid="6535018036285012028">"PIN kode hori ez da zuzena."</string>
     <string name="keyguard_sim_error_message_short" msgid="592109500618448312">"Txartelak ez du balio."</string>
-    <string name="keyguard_charged" msgid="3316115607283493413">"Erabat kargatuta"</string>
+    <string name="keyguard_charged" msgid="2222329688813033109">"Kargatuta"</string>
     <string name="keyguard_plugged_in_wireless" msgid="8404159927155454732">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Hari gabe kargatzen"</string>
     <string name="keyguard_plugged_in" msgid="3161102098900158923">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Kargatzen"</string>
     <string name="keyguard_plugged_in_charging_fast" msgid="3684592786276709342">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Bizkor kargatzen"</string>
diff --git a/packages/SystemUI/res-keyguard/values-fa/strings.xml b/packages/SystemUI/res-keyguard/values-fa/strings.xml
index 9c9de22..0bf01d9 100644
--- a/packages/SystemUI/res-keyguard/values-fa/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-fa/strings.xml
@@ -33,7 +33,7 @@
     <string name="keyguard_enter_your_password" msgid="5397328359341314506">"گذرواژه‌تان را وارد کنید"</string>
     <string name="keyguard_password_wrong_pin_code" msgid="6535018036285012028">"کد پین اشتباه است."</string>
     <string name="keyguard_sim_error_message_short" msgid="592109500618448312">"کارت نامعتبر"</string>
-    <string name="keyguard_charged" msgid="3316115607283493413">"شارژ کامل است"</string>
+    <string name="keyguard_charged" msgid="2222329688813033109">"شارژ کامل شد"</string>
     <string name="keyguard_plugged_in_wireless" msgid="8404159927155454732">"<xliff:g id="PERCENTAGE">%s</xliff:g> • درحال شارژ بی‌سیم"</string>
     <string name="keyguard_plugged_in" msgid="3161102098900158923">"<xliff:g id="PERCENTAGE">%s</xliff:g> • درحال شارژ شدن"</string>
     <string name="keyguard_plugged_in_charging_fast" msgid="3684592786276709342">"<xliff:g id="PERCENTAGE">%s</xliff:g> • درحال شارژ سریع"</string>
diff --git a/packages/SystemUI/res-keyguard/values-fi/strings.xml b/packages/SystemUI/res-keyguard/values-fi/strings.xml
index 66f1de5..9b727a4 100644
--- a/packages/SystemUI/res-keyguard/values-fi/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-fi/strings.xml
@@ -33,7 +33,7 @@
     <string name="keyguard_enter_your_password" msgid="5397328359341314506">"Kirjoita salasana"</string>
     <string name="keyguard_password_wrong_pin_code" msgid="6535018036285012028">"Väärä PIN-koodi"</string>
     <string name="keyguard_sim_error_message_short" msgid="592109500618448312">"Virheellinen kortti"</string>
-    <string name="keyguard_charged" msgid="3316115607283493413">"Täyteen ladattu"</string>
+    <string name="keyguard_charged" msgid="2222329688813033109">"Ladattu"</string>
     <string name="keyguard_plugged_in_wireless" msgid="8404159927155454732">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Ladataan langattomasti"</string>
     <string name="keyguard_plugged_in" msgid="3161102098900158923">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Ladataan"</string>
     <string name="keyguard_plugged_in_charging_fast" msgid="3684592786276709342">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Ladataan nopeasti"</string>
@@ -74,7 +74,7 @@
     <string name="kg_sim_pin_instructions_multi" msgid="1643757228644271861">"Anna operaattorin <xliff:g id="CARRIER">%1$s</xliff:g> SIM-kortin PIN-koodi."</string>
     <string name="kg_sim_lock_esim_instructions" msgid="4416732549172148542">"<xliff:g id="PREVIOUS_MSG">%1$s</xliff:g> Poista eSIM käytöstä, jos haluat käyttää laitetta ilman mobiililiittymää."</string>
     <string name="kg_pin_instructions" msgid="4069609316644030034">"Anna PIN-koodi."</string>
-    <string name="kg_password_instructions" msgid="136952397352976538">"Anna salasana"</string>
+    <string name="kg_password_instructions" msgid="136952397352976538">"Lisää salasana"</string>
     <string name="kg_puk_enter_puk_hint" msgid="2288964170039899277">"SIM-kortti on nyt poistettu käytöstä. Jatka antamalla PUK-koodi. Saat lisätietoja ottamalla yhteyttä operaattoriin."</string>
     <string name="kg_puk_enter_puk_hint_multi" msgid="1373131883510840794">"Operaattorin <xliff:g id="CARRIER">%1$s</xliff:g> SIM-kortti on nyt lukittu. Jatka antamalla PUK-koodi. Saat lisätietoja operaattoriltasi."</string>
     <string name="kg_puk_enter_pin_hint" msgid="3137789674920391087">"Anna haluamasi PIN-koodi."</string>
diff --git a/packages/SystemUI/res-keyguard/values-fr-rCA/strings.xml b/packages/SystemUI/res-keyguard/values-fr-rCA/strings.xml
index 66c7c86..a86cdbe 100644
--- a/packages/SystemUI/res-keyguard/values-fr-rCA/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-fr-rCA/strings.xml
@@ -33,7 +33,7 @@
     <string name="keyguard_enter_your_password" msgid="5397328359341314506">"Entrez votre mot de passe"</string>
     <string name="keyguard_password_wrong_pin_code" msgid="6535018036285012028">"NIP erroné."</string>
     <string name="keyguard_sim_error_message_short" msgid="592109500618448312">"Cette carte n\'est pas valide."</string>
-    <string name="keyguard_charged" msgid="3316115607283493413">"Complètement chargé"</string>
+    <string name="keyguard_charged" msgid="2222329688813033109">"Chargé"</string>
     <string name="keyguard_plugged_in_wireless" msgid="8404159927155454732">"<xliff:g id="PERCENTAGE">%s</xliff:g> • En recharge sans fil"</string>
     <string name="keyguard_plugged_in" msgid="3161102098900158923">"En recharge : <xliff:g id="PERCENTAGE">%s</xliff:g>"</string>
     <string name="keyguard_plugged_in_charging_fast" msgid="3684592786276709342">"En recharge rapide : <xliff:g id="PERCENTAGE">%s</xliff:g>"</string>
diff --git a/packages/SystemUI/res-keyguard/values-fr/strings.xml b/packages/SystemUI/res-keyguard/values-fr/strings.xml
index d6aa5d2..70075ec 100644
--- a/packages/SystemUI/res-keyguard/values-fr/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-fr/strings.xml
@@ -33,7 +33,7 @@
     <string name="keyguard_enter_your_password" msgid="5397328359341314506">"Saisissez votre mot de passe"</string>
     <string name="keyguard_password_wrong_pin_code" msgid="6535018036285012028">"Le code est incorrect."</string>
     <string name="keyguard_sim_error_message_short" msgid="592109500618448312">"Carte non valide."</string>
-    <string name="keyguard_charged" msgid="3316115607283493413">"Complètement chargée"</string>
+    <string name="keyguard_charged" msgid="2222329688813033109">"Chargé"</string>
     <string name="keyguard_plugged_in_wireless" msgid="8404159927155454732">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Recharge sans fil"</string>
     <string name="keyguard_plugged_in" msgid="3161102098900158923">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Recharge…"</string>
     <string name="keyguard_plugged_in_charging_fast" msgid="3684592786276709342">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Recharge rapide…"</string>
diff --git a/packages/SystemUI/res-keyguard/values-gl/strings.xml b/packages/SystemUI/res-keyguard/values-gl/strings.xml
index e6b10a0..9504a3e 100644
--- a/packages/SystemUI/res-keyguard/values-gl/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-gl/strings.xml
@@ -33,7 +33,7 @@
     <string name="keyguard_enter_your_password" msgid="5397328359341314506">"Introduce o contrasinal"</string>
     <string name="keyguard_password_wrong_pin_code" msgid="6535018036285012028">"Código PIN incorrecto"</string>
     <string name="keyguard_sim_error_message_short" msgid="592109500618448312">"A tarxeta non é válida."</string>
-    <string name="keyguard_charged" msgid="3316115607283493413">"Batería totalmente cargada"</string>
+    <string name="keyguard_charged" msgid="2222329688813033109">"Cargada"</string>
     <string name="keyguard_plugged_in_wireless" msgid="8404159927155454732">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Cargando sen fíos"</string>
     <string name="keyguard_plugged_in" msgid="3161102098900158923">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Cargando"</string>
     <string name="keyguard_plugged_in_charging_fast" msgid="3684592786276709342">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Cargando rapidamente"</string>
diff --git a/packages/SystemUI/res-keyguard/values-gu/strings.xml b/packages/SystemUI/res-keyguard/values-gu/strings.xml
index 025462e..a2370d0 100644
--- a/packages/SystemUI/res-keyguard/values-gu/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-gu/strings.xml
@@ -33,7 +33,7 @@
     <string name="keyguard_enter_your_password" msgid="5397328359341314506">"તમારો પાસવર્ડ દાખલ કરો"</string>
     <string name="keyguard_password_wrong_pin_code" msgid="6535018036285012028">"ખોટો પિન કોડ."</string>
     <string name="keyguard_sim_error_message_short" msgid="592109500618448312">"અમાન્ય કાર્ડ."</string>
-    <string name="keyguard_charged" msgid="3316115607283493413">"સંપૂર્ણપણે ચાર્જ થયેલ"</string>
+    <string name="keyguard_charged" msgid="2222329688813033109">"ચાર્જ થઈ ગયું"</string>
     <string name="keyguard_plugged_in_wireless" msgid="8404159927155454732">"<xliff:g id="PERCENTAGE">%s</xliff:g> • વાયરલેસથી ચાર્જિંગ"</string>
     <string name="keyguard_plugged_in" msgid="3161102098900158923">"<xliff:g id="PERCENTAGE">%s</xliff:g> • ચાર્જિંગ"</string>
     <string name="keyguard_plugged_in_charging_fast" msgid="3684592786276709342">"<xliff:g id="PERCENTAGE">%s</xliff:g> • ઝડપથી ચાર્જિંગ"</string>
diff --git a/packages/SystemUI/res-keyguard/values-hi/strings.xml b/packages/SystemUI/res-keyguard/values-hi/strings.xml
index 2de75e4..f8e99a6 100644
--- a/packages/SystemUI/res-keyguard/values-hi/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-hi/strings.xml
@@ -33,7 +33,7 @@
     <string name="keyguard_enter_your_password" msgid="5397328359341314506">"अपना पासवर्ड डालें"</string>
     <string name="keyguard_password_wrong_pin_code" msgid="6535018036285012028">"गलत पिन कोड."</string>
     <string name="keyguard_sim_error_message_short" msgid="592109500618448312">"गलत कार्ड."</string>
-    <string name="keyguard_charged" msgid="3316115607283493413">"पूरी तरह चार्ज हो गया"</string>
+    <string name="keyguard_charged" msgid="2222329688813033109">"चार्ज हो गई है"</string>
     <string name="keyguard_plugged_in_wireless" msgid="8404159927155454732">"<xliff:g id="PERCENTAGE">%s</xliff:g> • वायरलेस तरीके से चार्ज हो रहा है"</string>
     <string name="keyguard_plugged_in" msgid="3161102098900158923">"<xliff:g id="PERCENTAGE">%s</xliff:g> • चार्ज हो रहा है"</string>
     <string name="keyguard_plugged_in_charging_fast" msgid="3684592786276709342">"<xliff:g id="PERCENTAGE">%s</xliff:g> • तेज़ चार्ज हो रहा है"</string>
diff --git a/packages/SystemUI/res-keyguard/values-hr/strings.xml b/packages/SystemUI/res-keyguard/values-hr/strings.xml
index c4f7bba..1c9396a 100644
--- a/packages/SystemUI/res-keyguard/values-hr/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-hr/strings.xml
@@ -33,7 +33,7 @@
     <string name="keyguard_enter_your_password" msgid="5397328359341314506">"Unesite zaporku"</string>
     <string name="keyguard_password_wrong_pin_code" msgid="6535018036285012028">"PIN kôd nije točan."</string>
     <string name="keyguard_sim_error_message_short" msgid="592109500618448312">"Nevažeća kartica."</string>
-    <string name="keyguard_charged" msgid="3316115607283493413">"Potpuno napunjena baterija"</string>
+    <string name="keyguard_charged" msgid="2222329688813033109">"Napunjeno"</string>
     <string name="keyguard_plugged_in_wireless" msgid="8404159927155454732">"<xliff:g id="PERCENTAGE">%s</xliff:g> • bežično punjenje"</string>
     <string name="keyguard_plugged_in" msgid="3161102098900158923">"<xliff:g id="PERCENTAGE">%s</xliff:g> • punjenje"</string>
     <string name="keyguard_plugged_in_charging_fast" msgid="3684592786276709342">"<xliff:g id="PERCENTAGE">%s</xliff:g> • brzo punjenje"</string>
diff --git a/packages/SystemUI/res-keyguard/values-hu/strings.xml b/packages/SystemUI/res-keyguard/values-hu/strings.xml
index 06142bc..ea5ab94 100644
--- a/packages/SystemUI/res-keyguard/values-hu/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-hu/strings.xml
@@ -33,7 +33,7 @@
     <string name="keyguard_enter_your_password" msgid="5397328359341314506">"Adja meg jelszavát"</string>
     <string name="keyguard_password_wrong_pin_code" msgid="6535018036285012028">"Helytelen PIN-kód."</string>
     <string name="keyguard_sim_error_message_short" msgid="592109500618448312">"Érvénytelen kártya."</string>
-    <string name="keyguard_charged" msgid="3316115607283493413">"Teljesen feltöltve"</string>
+    <string name="keyguard_charged" msgid="2222329688813033109">"Feltöltve"</string>
     <string name="keyguard_plugged_in_wireless" msgid="8404159927155454732">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Vezeték nélküli töltés"</string>
     <string name="keyguard_plugged_in" msgid="3161102098900158923">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Töltés"</string>
     <string name="keyguard_plugged_in_charging_fast" msgid="3684592786276709342">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Gyors töltés"</string>
diff --git a/packages/SystemUI/res-keyguard/values-hy/strings.xml b/packages/SystemUI/res-keyguard/values-hy/strings.xml
index f501fcc..b34eced 100644
--- a/packages/SystemUI/res-keyguard/values-hy/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-hy/strings.xml
@@ -33,7 +33,7 @@
     <string name="keyguard_enter_your_password" msgid="5397328359341314506">"Մուտքագրեք գաղտնաբառը"</string>
     <string name="keyguard_password_wrong_pin_code" msgid="6535018036285012028">"PIN կոդը սխալ է։"</string>
     <string name="keyguard_sim_error_message_short" msgid="592109500618448312">"Սխալ քարտ"</string>
-    <string name="keyguard_charged" msgid="3316115607283493413">"Ամբողջությամբ լիցքավորված է"</string>
+    <string name="keyguard_charged" msgid="2222329688813033109">"Լիցքավորված է"</string>
     <string name="keyguard_plugged_in_wireless" msgid="8404159927155454732">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Անլար լիցքավորում"</string>
     <string name="keyguard_plugged_in" msgid="3161102098900158923">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Լիցքավորում"</string>
     <string name="keyguard_plugged_in_charging_fast" msgid="3684592786276709342">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Արագ լիցքավորում"</string>
diff --git a/packages/SystemUI/res-keyguard/values-in/strings.xml b/packages/SystemUI/res-keyguard/values-in/strings.xml
index 64f396e..3dd6c91 100644
--- a/packages/SystemUI/res-keyguard/values-in/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-in/strings.xml
@@ -33,7 +33,7 @@
     <string name="keyguard_enter_your_password" msgid="5397328359341314506">"Masukkan sandi"</string>
     <string name="keyguard_password_wrong_pin_code" msgid="6535018036285012028">"Kode PIN salah."</string>
     <string name="keyguard_sim_error_message_short" msgid="592109500618448312">"Kartu Tidak Valid"</string>
-    <string name="keyguard_charged" msgid="3316115607283493413">"Terisi penuh"</string>
+    <string name="keyguard_charged" msgid="2222329688813033109">"Terisi"</string>
     <string name="keyguard_plugged_in_wireless" msgid="8404159927155454732">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Mengisi daya secara nirkabel"</string>
     <string name="keyguard_plugged_in" msgid="3161102098900158923">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Mengisi daya"</string>
     <string name="keyguard_plugged_in_charging_fast" msgid="3684592786276709342">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Mengisi daya dengan cepat"</string>
diff --git a/packages/SystemUI/res-keyguard/values-is/strings.xml b/packages/SystemUI/res-keyguard/values-is/strings.xml
index aa33215..c09dcc6 100644
--- a/packages/SystemUI/res-keyguard/values-is/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-is/strings.xml
@@ -33,7 +33,7 @@
     <string name="keyguard_enter_your_password" msgid="5397328359341314506">"Sláðu inn aðgangsorðið þitt"</string>
     <string name="keyguard_password_wrong_pin_code" msgid="6535018036285012028">"Rangt PIN-númer."</string>
     <string name="keyguard_sim_error_message_short" msgid="592109500618448312">"Ógilt kort."</string>
-    <string name="keyguard_charged" msgid="3316115607283493413">"Fullhlaðin"</string>
+    <string name="keyguard_charged" msgid="2222329688813033109">"Fullhlaðin"</string>
     <string name="keyguard_plugged_in_wireless" msgid="8404159927155454732">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Í þráðlausri hleðslu"</string>
     <string name="keyguard_plugged_in" msgid="3161102098900158923">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Í hleðslu"</string>
     <string name="keyguard_plugged_in_charging_fast" msgid="3684592786276709342">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Hröð hleðsla"</string>
diff --git a/packages/SystemUI/res-keyguard/values-it/strings.xml b/packages/SystemUI/res-keyguard/values-it/strings.xml
index 761640c..3f5cfbb 100644
--- a/packages/SystemUI/res-keyguard/values-it/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-it/strings.xml
@@ -33,7 +33,7 @@
     <string name="keyguard_enter_your_password" msgid="5397328359341314506">"Inserisci la password"</string>
     <string name="keyguard_password_wrong_pin_code" msgid="6535018036285012028">"Codice PIN errato."</string>
     <string name="keyguard_sim_error_message_short" msgid="592109500618448312">"Scheda non valida."</string>
-    <string name="keyguard_charged" msgid="3316115607283493413">"Completamente carica"</string>
+    <string name="keyguard_charged" msgid="2222329688813033109">"Carico"</string>
     <string name="keyguard_plugged_in_wireless" msgid="8404159927155454732">"<xliff:g id="PERCENTAGE">%s</xliff:g> • In carica wireless"</string>
     <string name="keyguard_plugged_in" msgid="3161102098900158923">"<xliff:g id="PERCENTAGE">%s</xliff:g> • In carica"</string>
     <string name="keyguard_plugged_in_charging_fast" msgid="3684592786276709342">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Ricarica veloce"</string>
diff --git a/packages/SystemUI/res-keyguard/values-iw/strings.xml b/packages/SystemUI/res-keyguard/values-iw/strings.xml
index e72c808..95caf91 100644
--- a/packages/SystemUI/res-keyguard/values-iw/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-iw/strings.xml
@@ -33,7 +33,7 @@
     <string name="keyguard_enter_your_password" msgid="5397328359341314506">"יש להזין סיסמה"</string>
     <string name="keyguard_password_wrong_pin_code" msgid="6535018036285012028">"קוד הגישה שגוי"</string>
     <string name="keyguard_sim_error_message_short" msgid="592109500618448312">"כרטיס לא חוקי."</string>
-    <string name="keyguard_charged" msgid="3316115607283493413">"טעונה במלואה"</string>
+    <string name="keyguard_charged" msgid="2222329688813033109">"הסוללה טעונה"</string>
     <string name="keyguard_plugged_in_wireless" msgid="8404159927155454732">"<xliff:g id="PERCENTAGE">%s</xliff:g> • בטעינה אלחוטית"</string>
     <string name="keyguard_plugged_in" msgid="3161102098900158923">"<xliff:g id="PERCENTAGE">%s</xliff:g> • בטעינה"</string>
     <string name="keyguard_plugged_in_charging_fast" msgid="3684592786276709342">"<xliff:g id="PERCENTAGE">%s</xliff:g> • בטעינה מהירה"</string>
diff --git a/packages/SystemUI/res-keyguard/values-ja/strings.xml b/packages/SystemUI/res-keyguard/values-ja/strings.xml
index 27adb8c..9872a07 100644
--- a/packages/SystemUI/res-keyguard/values-ja/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-ja/strings.xml
@@ -33,7 +33,7 @@
     <string name="keyguard_enter_your_password" msgid="5397328359341314506">"パスワードを入力してください"</string>
     <string name="keyguard_password_wrong_pin_code" msgid="6535018036285012028">"PIN コードが無効です。"</string>
     <string name="keyguard_sim_error_message_short" msgid="592109500618448312">"無効なカードです。"</string>
-    <string name="keyguard_charged" msgid="3316115607283493413">"充電完了"</string>
+    <string name="keyguard_charged" msgid="2222329688813033109">"充電が完了しました"</string>
     <string name="keyguard_plugged_in_wireless" msgid="8404159927155454732">"<xliff:g id="PERCENTAGE">%s</xliff:g> • ワイヤレス充電中"</string>
     <string name="keyguard_plugged_in" msgid="3161102098900158923">"<xliff:g id="PERCENTAGE">%s</xliff:g> • 充電中"</string>
     <string name="keyguard_plugged_in_charging_fast" msgid="3684592786276709342">"<xliff:g id="PERCENTAGE">%s</xliff:g> • 急速充電中"</string>
diff --git a/packages/SystemUI/res-keyguard/values-ka/strings.xml b/packages/SystemUI/res-keyguard/values-ka/strings.xml
index d165230..c3b5047 100644
--- a/packages/SystemUI/res-keyguard/values-ka/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-ka/strings.xml
@@ -33,7 +33,7 @@
     <string name="keyguard_enter_your_password" msgid="5397328359341314506">"შეიყვანეთ პაროლი"</string>
     <string name="keyguard_password_wrong_pin_code" msgid="6535018036285012028">"PIN-კოდი არასწორია."</string>
     <string name="keyguard_sim_error_message_short" msgid="592109500618448312">"ბარათი არასწორია."</string>
-    <string name="keyguard_charged" msgid="3316115607283493413">"ბოლომდე დატენილი"</string>
+    <string name="keyguard_charged" msgid="2222329688813033109">"დატენილია"</string>
     <string name="keyguard_plugged_in_wireless" msgid="8404159927155454732">"<xliff:g id="PERCENTAGE">%s</xliff:g> • იტენება უსადენოდ"</string>
     <string name="keyguard_plugged_in" msgid="3161102098900158923">"<xliff:g id="PERCENTAGE">%s</xliff:g> • იტენება"</string>
     <string name="keyguard_plugged_in_charging_fast" msgid="3684592786276709342">"<xliff:g id="PERCENTAGE">%s</xliff:g> • სწრაფად იტენება"</string>
diff --git a/packages/SystemUI/res-keyguard/values-kk/strings.xml b/packages/SystemUI/res-keyguard/values-kk/strings.xml
index 8522346..e8741f9 100644
--- a/packages/SystemUI/res-keyguard/values-kk/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-kk/strings.xml
@@ -33,7 +33,7 @@
     <string name="keyguard_enter_your_password" msgid="5397328359341314506">"Құпия сөзді енгізіңіз"</string>
     <string name="keyguard_password_wrong_pin_code" msgid="6535018036285012028">"PIN коды қате"</string>
     <string name="keyguard_sim_error_message_short" msgid="592109500618448312">"Жарамсыз карта."</string>
-    <string name="keyguard_charged" msgid="3316115607283493413">"Толық зарядталды"</string>
+    <string name="keyguard_charged" msgid="2222329688813033109">"Зарядталды"</string>
     <string name="keyguard_plugged_in_wireless" msgid="8404159927155454732">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Сымсыз зарядталуда"</string>
     <string name="keyguard_plugged_in" msgid="3161102098900158923">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Зарядталуда"</string>
     <string name="keyguard_plugged_in_charging_fast" msgid="3684592786276709342">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Жылдам зарядталуда"</string>
diff --git a/packages/SystemUI/res-keyguard/values-km/strings.xml b/packages/SystemUI/res-keyguard/values-km/strings.xml
index 7b4266a..d48de15 100644
--- a/packages/SystemUI/res-keyguard/values-km/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-km/strings.xml
@@ -33,7 +33,7 @@
     <string name="keyguard_enter_your_password" msgid="5397328359341314506">"បញ្ចូល​ពាក្យ​សម្ងាត់​របស់អ្នក"</string>
     <string name="keyguard_password_wrong_pin_code" msgid="6535018036285012028">"កូដ PIN មិន​ត្រឹមត្រូវ​ទេ។"</string>
     <string name="keyguard_sim_error_message_short" msgid="592109500618448312">"បណ្ណមិនត្រឹមត្រូវទេ។"</string>
-    <string name="keyguard_charged" msgid="3316115607283493413">"បានសាក​ថ្មពេញ"</string>
+    <string name="keyguard_charged" msgid="2222329688813033109">"បាន​សាក​ថ្ម"</string>
     <string name="keyguard_plugged_in_wireless" msgid="8404159927155454732">"<xliff:g id="PERCENTAGE">%s</xliff:g> • កំពុងសាកថ្ម​ឥតខ្សែ"</string>
     <string name="keyguard_plugged_in" msgid="3161102098900158923">"<xliff:g id="PERCENTAGE">%s</xliff:g> • កំពុង​សាកថ្ម"</string>
     <string name="keyguard_plugged_in_charging_fast" msgid="3684592786276709342">"<xliff:g id="PERCENTAGE">%s</xliff:g> • កំពុង​សាកថ្មយ៉ាង​ឆាប់រហ័ស"</string>
diff --git a/packages/SystemUI/res-keyguard/values-kn/strings.xml b/packages/SystemUI/res-keyguard/values-kn/strings.xml
index eaaa829..7a6a0bf 100644
--- a/packages/SystemUI/res-keyguard/values-kn/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-kn/strings.xml
@@ -33,7 +33,7 @@
     <string name="keyguard_enter_your_password" msgid="5397328359341314506">"ನಿಮ್ಮ ಪಾಸ್‌ವರ್ಡ್ ನಮೂದಿಸಿ"</string>
     <string name="keyguard_password_wrong_pin_code" msgid="6535018036285012028">"ತಪ್ಪಾದ ಪಿನ್‌ ಕೋಡ್."</string>
     <string name="keyguard_sim_error_message_short" msgid="592109500618448312">"ಅಮಾನ್ಯ ಕಾರ್ಡ್."</string>
-    <string name="keyguard_charged" msgid="3316115607283493413">"ಪೂರ್ಣವಾಗಿ ಚಾರ್ಜ್ ಆಗಿದೆ"</string>
+    <string name="keyguard_charged" msgid="2222329688813033109">"ಚಾರ್ಜ್ ಆಗಿದೆ"</string>
     <string name="keyguard_plugged_in_wireless" msgid="8404159927155454732">"<xliff:g id="PERCENTAGE">%s</xliff:g> • ವೈರ್‌ಲೆಸ್ ಆಗಿ ಚಾರ್ಜ್ ಆಗುತ್ತಿದೆ"</string>
     <string name="keyguard_plugged_in" msgid="3161102098900158923">"<xliff:g id="PERCENTAGE">%s</xliff:g> • ಚಾರ್ಜ್‌ ಮಾಡಲಾಗುತ್ತಿದೆ"</string>
     <string name="keyguard_plugged_in_charging_fast" msgid="3684592786276709342">"<xliff:g id="PERCENTAGE">%s</xliff:g> • ವೇಗವಾಗಿ ಚಾರ್ಜ್‌ಮಾಡಲಾಗುತ್ತಿದೆ"</string>
diff --git a/packages/SystemUI/res-keyguard/values-ko/strings.xml b/packages/SystemUI/res-keyguard/values-ko/strings.xml
index ca84937..9c1ffc8 100644
--- a/packages/SystemUI/res-keyguard/values-ko/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-ko/strings.xml
@@ -33,7 +33,7 @@
     <string name="keyguard_enter_your_password" msgid="5397328359341314506">"비밀번호 입력"</string>
     <string name="keyguard_password_wrong_pin_code" msgid="6535018036285012028">"잘못된 PIN 코드입니다."</string>
     <string name="keyguard_sim_error_message_short" msgid="592109500618448312">"유효하지 않은 카드"</string>
-    <string name="keyguard_charged" msgid="3316115607283493413">"충전 완료"</string>
+    <string name="keyguard_charged" msgid="2222329688813033109">"충전됨"</string>
     <string name="keyguard_plugged_in_wireless" msgid="8404159927155454732">"<xliff:g id="PERCENTAGE">%s</xliff:g> • 무선 충전 중"</string>
     <string name="keyguard_plugged_in" msgid="3161102098900158923">"<xliff:g id="PERCENTAGE">%s</xliff:g> • 충전 중"</string>
     <string name="keyguard_plugged_in_charging_fast" msgid="3684592786276709342">"<xliff:g id="PERCENTAGE">%s</xliff:g> • 고속 충전 중"</string>
diff --git a/packages/SystemUI/res-keyguard/values-ky/strings.xml b/packages/SystemUI/res-keyguard/values-ky/strings.xml
index 805a567..a106000 100644
--- a/packages/SystemUI/res-keyguard/values-ky/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-ky/strings.xml
@@ -33,7 +33,7 @@
     <string name="keyguard_enter_your_password" msgid="5397328359341314506">"Сырсөзүңүздү киргизиңиз"</string>
     <string name="keyguard_password_wrong_pin_code" msgid="6535018036285012028">"PIN-код туура эмес."</string>
     <string name="keyguard_sim_error_message_short" msgid="592109500618448312">"SIM-карта жараксыз."</string>
-    <string name="keyguard_charged" msgid="3316115607283493413">"Толук кубатталды"</string>
+    <string name="keyguard_charged" msgid="2222329688813033109">"Кубатталды"</string>
     <string name="keyguard_plugged_in_wireless" msgid="8404159927155454732">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Зымсыз кубатталууда"</string>
     <string name="keyguard_plugged_in" msgid="3161102098900158923">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Кубатталууда"</string>
     <string name="keyguard_plugged_in_charging_fast" msgid="3684592786276709342">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Тез кубатталууда"</string>
diff --git a/packages/SystemUI/res-keyguard/values-lo/strings.xml b/packages/SystemUI/res-keyguard/values-lo/strings.xml
index 1418d27..e4d66a7 100644
--- a/packages/SystemUI/res-keyguard/values-lo/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-lo/strings.xml
@@ -33,7 +33,7 @@
     <string name="keyguard_enter_your_password" msgid="5397328359341314506">"ປ້ອນລະຫັດຜ່ານຂອງທ່ານ"</string>
     <string name="keyguard_password_wrong_pin_code" msgid="6535018036285012028">"ລະຫັດ PIN ບໍ່ຖືກຕ້ອງ."</string>
     <string name="keyguard_sim_error_message_short" msgid="592109500618448312">"ບັດບໍ່ຖືກຕ້ອງ."</string>
-    <string name="keyguard_charged" msgid="3316115607283493413">"ສາກເຕັມແລ້ວ"</string>
+    <string name="keyguard_charged" msgid="2222329688813033109">"ສາກເຕັມແລ້ວ."</string>
     <string name="keyguard_plugged_in_wireless" msgid="8404159927155454732">"<xliff:g id="PERCENTAGE">%s</xliff:g> • ກຳ​ລັງ​ສາກ​ໄຟໄຮ້​ສາຍ"</string>
     <string name="keyguard_plugged_in" msgid="3161102098900158923">"<xliff:g id="PERCENTAGE">%s</xliff:g> • ກຳລັງສາກ"</string>
     <string name="keyguard_plugged_in_charging_fast" msgid="3684592786276709342">"<xliff:g id="PERCENTAGE">%s</xliff:g> • ກຳລັງສາກແບບດ່ວນ"</string>
diff --git a/packages/SystemUI/res-keyguard/values-lt/strings.xml b/packages/SystemUI/res-keyguard/values-lt/strings.xml
index bbd25b2..30e7cad 100644
--- a/packages/SystemUI/res-keyguard/values-lt/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-lt/strings.xml
@@ -33,7 +33,7 @@
     <string name="keyguard_enter_your_password" msgid="5397328359341314506">"Įveskite slaptažodį"</string>
     <string name="keyguard_password_wrong_pin_code" msgid="6535018036285012028">"Netinkamas PIN kodas."</string>
     <string name="keyguard_sim_error_message_short" msgid="592109500618448312">"Netinkama kortelė."</string>
-    <string name="keyguard_charged" msgid="3316115607283493413">"Visiškai įkrautas"</string>
+    <string name="keyguard_charged" msgid="2222329688813033109">"Įkrauta"</string>
     <string name="keyguard_plugged_in_wireless" msgid="8404159927155454732">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Kraunama be laidų"</string>
     <string name="keyguard_plugged_in" msgid="3161102098900158923">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Įkraunama"</string>
     <string name="keyguard_plugged_in_charging_fast" msgid="3684592786276709342">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Greitai įkraunama"</string>
diff --git a/packages/SystemUI/res-keyguard/values-lv/strings.xml b/packages/SystemUI/res-keyguard/values-lv/strings.xml
index 58ca8ce..8cafcd3 100644
--- a/packages/SystemUI/res-keyguard/values-lv/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-lv/strings.xml
@@ -33,7 +33,7 @@
     <string name="keyguard_enter_your_password" msgid="5397328359341314506">"Ievadiet paroli"</string>
     <string name="keyguard_password_wrong_pin_code" msgid="6535018036285012028">"PIN kods nav pareizs."</string>
     <string name="keyguard_sim_error_message_short" msgid="592109500618448312">"Nederīga karte."</string>
-    <string name="keyguard_charged" msgid="3316115607283493413">"Pilnībā uzlādēts"</string>
+    <string name="keyguard_charged" msgid="2222329688813033109">"Akumulators uzlādēts"</string>
     <string name="keyguard_plugged_in_wireless" msgid="8404159927155454732">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Notiek bezvadu uzlāde"</string>
     <string name="keyguard_plugged_in" msgid="3161102098900158923">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Notiek uzlāde"</string>
     <string name="keyguard_plugged_in_charging_fast" msgid="3684592786276709342">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Notiek ātrā uzlāde"</string>
diff --git a/packages/SystemUI/res-keyguard/values-mk/strings.xml b/packages/SystemUI/res-keyguard/values-mk/strings.xml
index 1ffd8a4..e2ab170 100644
--- a/packages/SystemUI/res-keyguard/values-mk/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-mk/strings.xml
@@ -33,7 +33,7 @@
     <string name="keyguard_enter_your_password" msgid="5397328359341314506">"Внесете ја лозинката"</string>
     <string name="keyguard_password_wrong_pin_code" msgid="6535018036285012028">"Погрешен PIN-код."</string>
     <string name="keyguard_sim_error_message_short" msgid="592109500618448312">"Неважечка картичка."</string>
-    <string name="keyguard_charged" msgid="3316115607283493413">"Целосно полна"</string>
+    <string name="keyguard_charged" msgid="2222329688813033109">"Полна"</string>
     <string name="keyguard_plugged_in_wireless" msgid="8404159927155454732">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Се полни безжично"</string>
     <string name="keyguard_plugged_in" msgid="3161102098900158923">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Се полни"</string>
     <string name="keyguard_plugged_in_charging_fast" msgid="3684592786276709342">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Брзо полнење"</string>
diff --git a/packages/SystemUI/res-keyguard/values-ml/strings.xml b/packages/SystemUI/res-keyguard/values-ml/strings.xml
index 1f60c73..33765b4 100644
--- a/packages/SystemUI/res-keyguard/values-ml/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-ml/strings.xml
@@ -33,7 +33,7 @@
     <string name="keyguard_enter_your_password" msgid="5397328359341314506">"നിങ്ങളുടെ പാസ്‌വേഡ് നല്‍‌കുക"</string>
     <string name="keyguard_password_wrong_pin_code" msgid="6535018036285012028">"പിൻ കോഡ് തെറ്റാണ്."</string>
     <string name="keyguard_sim_error_message_short" msgid="592109500618448312">"അസാധുവായ കാർഡ്."</string>
-    <string name="keyguard_charged" msgid="3316115607283493413">"പൂർണ്ണമായി ചാർജ് ചെയ്‌തു"</string>
+    <string name="keyguard_charged" msgid="2222329688813033109">"ചാർജായി"</string>
     <string name="keyguard_plugged_in_wireless" msgid="8404159927155454732">"<xliff:g id="PERCENTAGE">%s</xliff:g> • വയർലെസ്സ് ആയി ചാർജ് ചെയ്യുന്നു"</string>
     <string name="keyguard_plugged_in" msgid="3161102098900158923">"<xliff:g id="PERCENTAGE">%s</xliff:g> • ചാർജ് ചെയ്യുന്നു"</string>
     <string name="keyguard_plugged_in_charging_fast" msgid="3684592786276709342">"<xliff:g id="PERCENTAGE">%s</xliff:g> • വേഗത്തിൽ ചാർജ് ചെയ്യുന്നു"</string>
diff --git a/packages/SystemUI/res-keyguard/values-mn/strings.xml b/packages/SystemUI/res-keyguard/values-mn/strings.xml
index 55dd70c..3451fb8 100644
--- a/packages/SystemUI/res-keyguard/values-mn/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-mn/strings.xml
@@ -33,7 +33,7 @@
     <string name="keyguard_enter_your_password" msgid="5397328359341314506">"Нууц үгээ оруулна уу"</string>
     <string name="keyguard_password_wrong_pin_code" msgid="6535018036285012028">"ПИН код буруу байна."</string>
     <string name="keyguard_sim_error_message_short" msgid="592109500618448312">"Карт хүчингүй байна."</string>
-    <string name="keyguard_charged" msgid="3316115607283493413">"Бүрэн цэнэглэсэн"</string>
+    <string name="keyguard_charged" msgid="2222329688813033109">"Цэнэглэсэн"</string>
     <string name="keyguard_plugged_in_wireless" msgid="8404159927155454732">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Утасгүй цэнэглэж байна"</string>
     <string name="keyguard_plugged_in" msgid="3161102098900158923">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Цэнэглэж байна"</string>
     <string name="keyguard_plugged_in_charging_fast" msgid="3684592786276709342">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Хурдан цэнэглэж байна"</string>
diff --git a/packages/SystemUI/res-keyguard/values-mr/strings.xml b/packages/SystemUI/res-keyguard/values-mr/strings.xml
index 0ba82e0..e86fa10 100644
--- a/packages/SystemUI/res-keyguard/values-mr/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-mr/strings.xml
@@ -33,7 +33,7 @@
     <string name="keyguard_enter_your_password" msgid="5397328359341314506">"तुमचा पासवर्ड एंटर करा"</string>
     <string name="keyguard_password_wrong_pin_code" msgid="6535018036285012028">"चुकीचा पिन कोड."</string>
     <string name="keyguard_sim_error_message_short" msgid="592109500618448312">"अवैध कार्ड."</string>
-    <string name="keyguard_charged" msgid="3316115607283493413">"पूर्णपणे चार्ज"</string>
+    <string name="keyguard_charged" msgid="2222329688813033109">"चार्ज झाली"</string>
     <string name="keyguard_plugged_in_wireless" msgid="8404159927155454732">"<xliff:g id="PERCENTAGE">%s</xliff:g> • वायरलेस पद्धतीने चार्ज करत आहे"</string>
     <string name="keyguard_plugged_in" msgid="3161102098900158923">"<xliff:g id="PERCENTAGE">%s</xliff:g> • चार्ज होत आहे"</string>
     <string name="keyguard_plugged_in_charging_fast" msgid="3684592786276709342">"<xliff:g id="PERCENTAGE">%s</xliff:g> • वेगाने चार्ज होत आहे"</string>
diff --git a/packages/SystemUI/res-keyguard/values-ms/strings.xml b/packages/SystemUI/res-keyguard/values-ms/strings.xml
index 17e1056..80ccd3e 100644
--- a/packages/SystemUI/res-keyguard/values-ms/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-ms/strings.xml
@@ -33,7 +33,7 @@
     <string name="keyguard_enter_your_password" msgid="5397328359341314506">"Masukkan kata laluan anda"</string>
     <string name="keyguard_password_wrong_pin_code" msgid="6535018036285012028">"Kod PIN salah."</string>
     <string name="keyguard_sim_error_message_short" msgid="592109500618448312">"Kad Tidak Sah."</string>
-    <string name="keyguard_charged" msgid="3316115607283493413">"Dicas penuh"</string>
+    <string name="keyguard_charged" msgid="2222329688813033109">"Sudah dicas"</string>
     <string name="keyguard_plugged_in_wireless" msgid="8404159927155454732">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Mengecas secara wayarles"</string>
     <string name="keyguard_plugged_in" msgid="3161102098900158923">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Mengecas"</string>
     <string name="keyguard_plugged_in_charging_fast" msgid="3684592786276709342">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Mengecas dengan cepat"</string>
diff --git a/packages/SystemUI/res-keyguard/values-my/strings.xml b/packages/SystemUI/res-keyguard/values-my/strings.xml
index 28fe2b2..c1fa6be 100644
--- a/packages/SystemUI/res-keyguard/values-my/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-my/strings.xml
@@ -33,7 +33,7 @@
     <string name="keyguard_enter_your_password" msgid="5397328359341314506">"သင့်စကားဝှက် ထည့်ပါ"</string>
     <string name="keyguard_password_wrong_pin_code" msgid="6535018036285012028">"ပင်နံပါတ် မှားနေသည်။"</string>
     <string name="keyguard_sim_error_message_short" msgid="592109500618448312">"ကတ် မမှန်ကန်ပါ။"</string>
-    <string name="keyguard_charged" msgid="3316115607283493413">"အားအပြည့်သွင်းထားသည်"</string>
+    <string name="keyguard_charged" msgid="2222329688813033109">"အားသွင်းပြီးပါပြီ"</string>
     <string name="keyguard_plugged_in_wireless" msgid="8404159927155454732">"<xliff:g id="PERCENTAGE">%s</xliff:g> • ကြိုးမဲ့ အားသွင်းနေသည်"</string>
     <string name="keyguard_plugged_in" msgid="3161102098900158923">"<xliff:g id="PERCENTAGE">%s</xliff:g> • အားသွင်းနေသည်"</string>
     <string name="keyguard_plugged_in_charging_fast" msgid="3684592786276709342">"<xliff:g id="PERCENTAGE">%s</xliff:g> • အမြန်အားသွင်းနေသည်"</string>
diff --git a/packages/SystemUI/res-keyguard/values-nb/strings.xml b/packages/SystemUI/res-keyguard/values-nb/strings.xml
index 692dcad..af99aa7 100644
--- a/packages/SystemUI/res-keyguard/values-nb/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-nb/strings.xml
@@ -33,7 +33,7 @@
     <string name="keyguard_enter_your_password" msgid="5397328359341314506">"Skriv inn passordet ditt"</string>
     <string name="keyguard_password_wrong_pin_code" msgid="6535018036285012028">"Feil PIN-kode."</string>
     <string name="keyguard_sim_error_message_short" msgid="592109500618448312">"Ugyldig kort."</string>
-    <string name="keyguard_charged" msgid="3316115607283493413">"Fulladet"</string>
+    <string name="keyguard_charged" msgid="2222329688813033109">"Oppladet"</string>
     <string name="keyguard_plugged_in_wireless" msgid="8404159927155454732">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Lader trådløst"</string>
     <string name="keyguard_plugged_in" msgid="3161102098900158923">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Lader"</string>
     <string name="keyguard_plugged_in_charging_fast" msgid="3684592786276709342">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Lader raskt"</string>
diff --git a/packages/SystemUI/res-keyguard/values-ne/strings.xml b/packages/SystemUI/res-keyguard/values-ne/strings.xml
index 8102021..82a4a19 100644
--- a/packages/SystemUI/res-keyguard/values-ne/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-ne/strings.xml
@@ -33,7 +33,7 @@
     <string name="keyguard_enter_your_password" msgid="5397328359341314506">"आफ्नो पासवर्ड प्रविष्ट गर्नु…"</string>
     <string name="keyguard_password_wrong_pin_code" msgid="6535018036285012028">"PIN कोड गलत छ।"</string>
     <string name="keyguard_sim_error_message_short" msgid="592109500618448312">"अमान्य कार्ड।"</string>
-    <string name="keyguard_charged" msgid="3316115607283493413">"पूर्ण चार्ज भएको"</string>
+    <string name="keyguard_charged" msgid="2222329688813033109">"चार्ज भयो"</string>
     <string name="keyguard_plugged_in_wireless" msgid="8404159927155454732">"<xliff:g id="PERCENTAGE">%s</xliff:g> • तारविनै चार्ज गर्दै"</string>
     <string name="keyguard_plugged_in" msgid="3161102098900158923">"<xliff:g id="PERCENTAGE">%s</xliff:g> • चार्ज गरिँदै"</string>
     <string name="keyguard_plugged_in_charging_fast" msgid="3684592786276709342">"<xliff:g id="PERCENTAGE">%s</xliff:g> • द्रुत गतिमा चार्ज गरिँदै"</string>
diff --git a/packages/SystemUI/res-keyguard/values-nl/strings.xml b/packages/SystemUI/res-keyguard/values-nl/strings.xml
index c79f2f7..c533956 100644
--- a/packages/SystemUI/res-keyguard/values-nl/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-nl/strings.xml
@@ -33,7 +33,7 @@
     <string name="keyguard_enter_your_password" msgid="5397328359341314506">"Geef je wachtwoord op"</string>
     <string name="keyguard_password_wrong_pin_code" msgid="6535018036285012028">"Onjuiste pincode."</string>
     <string name="keyguard_sim_error_message_short" msgid="592109500618448312">"Ongeldige kaart."</string>
-    <string name="keyguard_charged" msgid="3316115607283493413">"Volledig opgeladen"</string>
+    <string name="keyguard_charged" msgid="2222329688813033109">"Opgeladen"</string>
     <string name="keyguard_plugged_in_wireless" msgid="8404159927155454732">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Draadloos opladen"</string>
     <string name="keyguard_plugged_in" msgid="3161102098900158923">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Opladen"</string>
     <string name="keyguard_plugged_in_charging_fast" msgid="3684592786276709342">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Snel opladen"</string>
diff --git a/packages/SystemUI/res-keyguard/values-or/strings.xml b/packages/SystemUI/res-keyguard/values-or/strings.xml
index c28561a..258c2a8 100644
--- a/packages/SystemUI/res-keyguard/values-or/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-or/strings.xml
@@ -33,7 +33,7 @@
     <string name="keyguard_enter_your_password" msgid="5397328359341314506">"ନିଜ ପାସ୍‌ୱର୍ଡ ଲେଖନ୍ତୁ"</string>
     <string name="keyguard_password_wrong_pin_code" msgid="6535018036285012028">"ଭୁଲ PIN କୋଡ୍।"</string>
     <string name="keyguard_sim_error_message_short" msgid="592109500618448312">"ଅମାନ୍ୟ କାର୍ଡ।"</string>
-    <string name="keyguard_charged" msgid="3316115607283493413">"ସମ୍ପୂର୍ଣ୍ଣ ଭାବରେ ଚାର୍ଜ ହୋ‍ଇଗଲା"</string>
+    <string name="keyguard_charged" msgid="2222329688813033109">"ଚାର୍ଜ ହୋଇଗଲା"</string>
     <string name="keyguard_plugged_in_wireless" msgid="8404159927155454732">"ୱାୟାର୍‍ଲେସ୍‍ଭାବରେ <xliff:g id="PERCENTAGE">%s</xliff:g> • ଚାର୍ଜ ହୋଇଛି"</string>
     <string name="keyguard_plugged_in" msgid="3161102098900158923">"<xliff:g id="PERCENTAGE">%s</xliff:g> • ଚାର୍ଜ ହେଉଛି"</string>
     <string name="keyguard_plugged_in_charging_fast" msgid="3684592786276709342">"<xliff:g id="PERCENTAGE">%s</xliff:g> • ଦ୍ରୁତ ଭାବେ ଚାର୍ଜ ହେଉଛି"</string>
diff --git a/packages/SystemUI/res-keyguard/values-pa/strings.xml b/packages/SystemUI/res-keyguard/values-pa/strings.xml
index 01b5d8e..2c3f64e 100644
--- a/packages/SystemUI/res-keyguard/values-pa/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-pa/strings.xml
@@ -33,7 +33,7 @@
     <string name="keyguard_enter_your_password" msgid="5397328359341314506">"ਆਪਣਾ ਪਾਸਵਰਡ ਦਾਖਲ ਕਰੋ"</string>
     <string name="keyguard_password_wrong_pin_code" msgid="6535018036285012028">"ਗਲਤ ਪਿੰਨ ਕੋਡ।"</string>
     <string name="keyguard_sim_error_message_short" msgid="592109500618448312">"ਅਵੈਧ ਕਾਰਡ।"</string>
-    <string name="keyguard_charged" msgid="3316115607283493413">"ਪੂਰਾ ਚਾਰਜ"</string>
+    <string name="keyguard_charged" msgid="2222329688813033109">"ਚਾਰਜ ਹੋ ਗਿਆ"</string>
     <string name="keyguard_plugged_in_wireless" msgid="8404159927155454732">"<xliff:g id="PERCENTAGE">%s</xliff:g> • ਬਿਨਾਂ ਤਾਰ ਤੋਂ ਚਾਰਜ ਹੋ ਰਿਹਾ ਹੈ"</string>
     <string name="keyguard_plugged_in" msgid="3161102098900158923">"<xliff:g id="PERCENTAGE">%s</xliff:g> • ਚਾਰਜ ਹੋ ਰਿਹਾ ਹੈ"</string>
     <string name="keyguard_plugged_in_charging_fast" msgid="3684592786276709342">"<xliff:g id="PERCENTAGE">%s</xliff:g> • ਤੇਜ਼ੀ ਨਾਲ ਚਾਰਜ ਹੋ ਰਿਹਾ ਹੈ"</string>
diff --git a/packages/SystemUI/res-keyguard/values-pl/strings.xml b/packages/SystemUI/res-keyguard/values-pl/strings.xml
index f86a082..b88440f 100644
--- a/packages/SystemUI/res-keyguard/values-pl/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-pl/strings.xml
@@ -33,7 +33,7 @@
     <string name="keyguard_enter_your_password" msgid="5397328359341314506">"Wpisz hasło"</string>
     <string name="keyguard_password_wrong_pin_code" msgid="6535018036285012028">"Nieprawidłowy kod PIN."</string>
     <string name="keyguard_sim_error_message_short" msgid="592109500618448312">"Nieprawidłowa karta."</string>
-    <string name="keyguard_charged" msgid="3316115607283493413">"Bateria w pełni naładowana"</string>
+    <string name="keyguard_charged" msgid="2222329688813033109">"Naładowana"</string>
     <string name="keyguard_plugged_in_wireless" msgid="8404159927155454732">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Ładowanie bezprzewodowe"</string>
     <string name="keyguard_plugged_in" msgid="3161102098900158923">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Ładowanie"</string>
     <string name="keyguard_plugged_in_charging_fast" msgid="3684592786276709342">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Szybkie ładowanie"</string>
diff --git a/packages/SystemUI/res-keyguard/values-pt-rBR/strings.xml b/packages/SystemUI/res-keyguard/values-pt-rBR/strings.xml
index 436dd55..ed552d4 100644
--- a/packages/SystemUI/res-keyguard/values-pt-rBR/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-pt-rBR/strings.xml
@@ -33,7 +33,7 @@
     <string name="keyguard_enter_your_password" msgid="5397328359341314506">"Digite sua senha"</string>
     <string name="keyguard_password_wrong_pin_code" msgid="6535018036285012028">"Código PIN incorreto."</string>
     <string name="keyguard_sim_error_message_short" msgid="592109500618448312">"Cartão inválido."</string>
-    <string name="keyguard_charged" msgid="3316115607283493413">"Carga completa"</string>
+    <string name="keyguard_charged" msgid="2222329688813033109">"Carregada"</string>
     <string name="keyguard_plugged_in_wireless" msgid="8404159927155454732">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Carregando sem fio"</string>
     <string name="keyguard_plugged_in" msgid="3161102098900158923">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Carregando"</string>
     <string name="keyguard_plugged_in_charging_fast" msgid="3684592786276709342">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Carregando rapidamente"</string>
diff --git a/packages/SystemUI/res-keyguard/values-pt-rPT/strings.xml b/packages/SystemUI/res-keyguard/values-pt-rPT/strings.xml
index 2ba4268..5dd0beb 100644
--- a/packages/SystemUI/res-keyguard/values-pt-rPT/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-pt-rPT/strings.xml
@@ -33,7 +33,7 @@
     <string name="keyguard_enter_your_password" msgid="5397328359341314506">"Introduza a palavra-passe."</string>
     <string name="keyguard_password_wrong_pin_code" msgid="6535018036285012028">"Código PIN incorreto."</string>
     <string name="keyguard_sim_error_message_short" msgid="592109500618448312">"Cartão inválido."</string>
-    <string name="keyguard_charged" msgid="3316115607283493413">"Totalmente carregada"</string>
+    <string name="keyguard_charged" msgid="2222329688813033109">"Carregada"</string>
     <string name="keyguard_plugged_in_wireless" msgid="8404159927155454732">"<xliff:g id="PERCENTAGE">%s</xliff:g> • A carregar sem fios"</string>
     <string name="keyguard_plugged_in" msgid="3161102098900158923">"<xliff:g id="PERCENTAGE">%s</xliff:g> • A carregar…"</string>
     <string name="keyguard_plugged_in_charging_fast" msgid="3684592786276709342">"<xliff:g id="PERCENTAGE">%s</xliff:g> • A carregar rapidamente…"</string>
diff --git a/packages/SystemUI/res-keyguard/values-pt/strings.xml b/packages/SystemUI/res-keyguard/values-pt/strings.xml
index 436dd55..ed552d4 100644
--- a/packages/SystemUI/res-keyguard/values-pt/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-pt/strings.xml
@@ -33,7 +33,7 @@
     <string name="keyguard_enter_your_password" msgid="5397328359341314506">"Digite sua senha"</string>
     <string name="keyguard_password_wrong_pin_code" msgid="6535018036285012028">"Código PIN incorreto."</string>
     <string name="keyguard_sim_error_message_short" msgid="592109500618448312">"Cartão inválido."</string>
-    <string name="keyguard_charged" msgid="3316115607283493413">"Carga completa"</string>
+    <string name="keyguard_charged" msgid="2222329688813033109">"Carregada"</string>
     <string name="keyguard_plugged_in_wireless" msgid="8404159927155454732">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Carregando sem fio"</string>
     <string name="keyguard_plugged_in" msgid="3161102098900158923">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Carregando"</string>
     <string name="keyguard_plugged_in_charging_fast" msgid="3684592786276709342">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Carregando rapidamente"</string>
diff --git a/packages/SystemUI/res-keyguard/values-ro/strings.xml b/packages/SystemUI/res-keyguard/values-ro/strings.xml
index 6fdc958..13e15e3 100644
--- a/packages/SystemUI/res-keyguard/values-ro/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-ro/strings.xml
@@ -33,7 +33,7 @@
     <string name="keyguard_enter_your_password" msgid="5397328359341314506">"Introduceți parola"</string>
     <string name="keyguard_password_wrong_pin_code" msgid="6535018036285012028">"Cod PIN incorect."</string>
     <string name="keyguard_sim_error_message_short" msgid="592109500618448312">"Card nevalid"</string>
-    <string name="keyguard_charged" msgid="3316115607283493413">"Complet încărcată"</string>
+    <string name="keyguard_charged" msgid="2222329688813033109">"Încărcată"</string>
     <string name="keyguard_plugged_in_wireless" msgid="8404159927155454732">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Se încarcă wireless"</string>
     <string name="keyguard_plugged_in" msgid="3161102098900158923">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Se încarcă"</string>
     <string name="keyguard_plugged_in_charging_fast" msgid="3684592786276709342">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Se încarcă rapid"</string>
diff --git a/packages/SystemUI/res-keyguard/values-ru/strings.xml b/packages/SystemUI/res-keyguard/values-ru/strings.xml
index f9bd05b..781a3e4 100644
--- a/packages/SystemUI/res-keyguard/values-ru/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-ru/strings.xml
@@ -33,7 +33,7 @@
     <string name="keyguard_enter_your_password" msgid="5397328359341314506">"Введите пароль"</string>
     <string name="keyguard_password_wrong_pin_code" msgid="6535018036285012028">"Неверный PIN-код."</string>
     <string name="keyguard_sim_error_message_short" msgid="592109500618448312">"Ошибка SIM-карты."</string>
-    <string name="keyguard_charged" msgid="3316115607283493413">"Аккумулятор полностью заряжен"</string>
+    <string name="keyguard_charged" msgid="2222329688813033109">"Батарея заряжена"</string>
     <string name="keyguard_plugged_in_wireless" msgid="8404159927155454732">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Беспроводная зарядка"</string>
     <string name="keyguard_plugged_in" msgid="3161102098900158923">"Идет зарядка (<xliff:g id="PERCENTAGE">%s</xliff:g>)"</string>
     <string name="keyguard_plugged_in_charging_fast" msgid="3684592786276709342">"Идет быстрая зарядка (<xliff:g id="PERCENTAGE">%s</xliff:g>)"</string>
diff --git a/packages/SystemUI/res-keyguard/values-si/strings.xml b/packages/SystemUI/res-keyguard/values-si/strings.xml
index e40be05..e51aa96 100644
--- a/packages/SystemUI/res-keyguard/values-si/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-si/strings.xml
@@ -33,7 +33,7 @@
     <string name="keyguard_enter_your_password" msgid="5397328359341314506">"ඔබේ මුරපදය ඇතුළු කරන්න"</string>
     <string name="keyguard_password_wrong_pin_code" msgid="6535018036285012028">"වැරදි PIN කේතයකි."</string>
     <string name="keyguard_sim_error_message_short" msgid="592109500618448312">"වලංගු නොවන කාඩ්පත."</string>
-    <string name="keyguard_charged" msgid="3316115607283493413">"සම්පූර්ණයෙන් ආරෝපණය වී ඇත"</string>
+    <string name="keyguard_charged" msgid="2222329688813033109">"අරෝපිතයි"</string>
     <string name="keyguard_plugged_in_wireless" msgid="8404159927155454732">"<xliff:g id="PERCENTAGE">%s</xliff:g> • නොරැහැන්ව ආරෝපණ කෙරේ"</string>
     <string name="keyguard_plugged_in" msgid="3161102098900158923">"<xliff:g id="PERCENTAGE">%s</xliff:g> • ආරෝපණය වෙමින්"</string>
     <string name="keyguard_plugged_in_charging_fast" msgid="3684592786276709342">"<xliff:g id="PERCENTAGE">%s</xliff:g> • වේගයෙන් ආරෝපණය වෙමින්"</string>
diff --git a/packages/SystemUI/res-keyguard/values-sk/strings.xml b/packages/SystemUI/res-keyguard/values-sk/strings.xml
index e7800e9..4fe1e4f 100644
--- a/packages/SystemUI/res-keyguard/values-sk/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-sk/strings.xml
@@ -33,7 +33,7 @@
     <string name="keyguard_enter_your_password" msgid="5397328359341314506">"Zadajte heslo"</string>
     <string name="keyguard_password_wrong_pin_code" msgid="6535018036285012028">"Nesprávny kód PIN."</string>
     <string name="keyguard_sim_error_message_short" msgid="592109500618448312">"Neplatná karta."</string>
-    <string name="keyguard_charged" msgid="3316115607283493413">"Úplne nabité"</string>
+    <string name="keyguard_charged" msgid="2222329688813033109">"Nabité"</string>
     <string name="keyguard_plugged_in_wireless" msgid="8404159927155454732">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Nabíja sa bezdrôtovo"</string>
     <string name="keyguard_plugged_in" msgid="3161102098900158923">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Nabíja sa"</string>
     <string name="keyguard_plugged_in_charging_fast" msgid="3684592786276709342">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Nabíja sa rýchlo"</string>
diff --git a/packages/SystemUI/res-keyguard/values-sl/strings.xml b/packages/SystemUI/res-keyguard/values-sl/strings.xml
index cce3a31..822e162 100644
--- a/packages/SystemUI/res-keyguard/values-sl/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-sl/strings.xml
@@ -33,7 +33,7 @@
     <string name="keyguard_enter_your_password" msgid="5397328359341314506">"Vnesite geslo"</string>
     <string name="keyguard_password_wrong_pin_code" msgid="6535018036285012028">"Napačna koda PIN."</string>
     <string name="keyguard_sim_error_message_short" msgid="592109500618448312">"Neveljavna kartica"</string>
-    <string name="keyguard_charged" msgid="3316115607283493413">"Popolnoma napolnjen"</string>
+    <string name="keyguard_charged" msgid="2222329688813033109">"Akumulator napolnjen"</string>
     <string name="keyguard_plugged_in_wireless" msgid="8404159927155454732">"<xliff:g id="PERCENTAGE">%s</xliff:g> • brezžično polnjenje"</string>
     <string name="keyguard_plugged_in" msgid="3161102098900158923">"<xliff:g id="PERCENTAGE">%s</xliff:g> • polnjenje"</string>
     <string name="keyguard_plugged_in_charging_fast" msgid="3684592786276709342">"<xliff:g id="PERCENTAGE">%s</xliff:g> • hitro polnjenje"</string>
diff --git a/packages/SystemUI/res-keyguard/values-sq/strings.xml b/packages/SystemUI/res-keyguard/values-sq/strings.xml
index e4b37d0..4636e6a 100644
--- a/packages/SystemUI/res-keyguard/values-sq/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-sq/strings.xml
@@ -33,7 +33,7 @@
     <string name="keyguard_enter_your_password" msgid="5397328359341314506">"Fut fjalëkalimin"</string>
     <string name="keyguard_password_wrong_pin_code" msgid="6535018036285012028">"Kodi PIN është i pasaktë."</string>
     <string name="keyguard_sim_error_message_short" msgid="592109500618448312">"Karta e pavlefshme."</string>
-    <string name="keyguard_charged" msgid="3316115607283493413">"I ngarkuar plotësisht"</string>
+    <string name="keyguard_charged" msgid="2222329688813033109">"I ngarkuar"</string>
     <string name="keyguard_plugged_in_wireless" msgid="8404159927155454732">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Po karikohet me valë"</string>
     <string name="keyguard_plugged_in" msgid="3161102098900158923">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Po karikohet"</string>
     <string name="keyguard_plugged_in_charging_fast" msgid="3684592786276709342">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Po karikohet me shpejtësi"</string>
diff --git a/packages/SystemUI/res-keyguard/values-sr/strings.xml b/packages/SystemUI/res-keyguard/values-sr/strings.xml
index 1e6de94..033e93b 100644
--- a/packages/SystemUI/res-keyguard/values-sr/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-sr/strings.xml
@@ -33,7 +33,7 @@
     <string name="keyguard_enter_your_password" msgid="5397328359341314506">"Унесите лозинку"</string>
     <string name="keyguard_password_wrong_pin_code" msgid="6535018036285012028">"PIN кôд је нетачан."</string>
     <string name="keyguard_sim_error_message_short" msgid="592109500618448312">"Неважећа картица."</string>
-    <string name="keyguard_charged" msgid="3316115607283493413">"Напуњена је у потпуности"</string>
+    <string name="keyguard_charged" msgid="2222329688813033109">"Напуњена је"</string>
     <string name="keyguard_plugged_in_wireless" msgid="8404159927155454732">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Бежично пуњење"</string>
     <string name="keyguard_plugged_in" msgid="3161102098900158923">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Пуни се"</string>
     <string name="keyguard_plugged_in_charging_fast" msgid="3684592786276709342">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Брзо се пуни"</string>
diff --git a/packages/SystemUI/res-keyguard/values-sv/strings.xml b/packages/SystemUI/res-keyguard/values-sv/strings.xml
index 4cca176..8d7be97 100644
--- a/packages/SystemUI/res-keyguard/values-sv/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-sv/strings.xml
@@ -33,7 +33,7 @@
     <string name="keyguard_enter_your_password" msgid="5397328359341314506">"Ange ditt lösenord"</string>
     <string name="keyguard_password_wrong_pin_code" msgid="6535018036285012028">"Fel pinkod."</string>
     <string name="keyguard_sim_error_message_short" msgid="592109500618448312">"Ogiltigt kort."</string>
-    <string name="keyguard_charged" msgid="3316115607283493413">"Fulladdad"</string>
+    <string name="keyguard_charged" msgid="2222329688813033109">"Laddat"</string>
     <string name="keyguard_plugged_in_wireless" msgid="8404159927155454732">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Laddas trådlöst"</string>
     <string name="keyguard_plugged_in" msgid="3161102098900158923">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Laddas"</string>
     <string name="keyguard_plugged_in_charging_fast" msgid="3684592786276709342">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Laddas snabbt"</string>
diff --git a/packages/SystemUI/res-keyguard/values-sw/strings.xml b/packages/SystemUI/res-keyguard/values-sw/strings.xml
index df51859..5ab4d07 100644
--- a/packages/SystemUI/res-keyguard/values-sw/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-sw/strings.xml
@@ -33,7 +33,7 @@
     <string name="keyguard_enter_your_password" msgid="5397328359341314506">"Weka nenosiri lako"</string>
     <string name="keyguard_password_wrong_pin_code" msgid="6535018036285012028">"Nambari ya PIN si sahihi."</string>
     <string name="keyguard_sim_error_message_short" msgid="592109500618448312">"Kadi si Sahihi."</string>
-    <string name="keyguard_charged" msgid="3316115607283493413">"Imejaa chaji"</string>
+    <string name="keyguard_charged" msgid="2222329688813033109">"Betri imejaa"</string>
     <string name="keyguard_plugged_in_wireless" msgid="8404159927155454732">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Inachaji bila kutumia waya"</string>
     <string name="keyguard_plugged_in" msgid="3161102098900158923">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Inachaji"</string>
     <string name="keyguard_plugged_in_charging_fast" msgid="3684592786276709342">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Inachaji kwa kasi"</string>
diff --git a/packages/SystemUI/res-keyguard/values-ta/strings.xml b/packages/SystemUI/res-keyguard/values-ta/strings.xml
index 9aa1972..fa75b4d 100644
--- a/packages/SystemUI/res-keyguard/values-ta/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-ta/strings.xml
@@ -33,7 +33,7 @@
     <string name="keyguard_enter_your_password" msgid="5397328359341314506">"கடவுச்சொல்லை உள்ளிடுக"</string>
     <string name="keyguard_password_wrong_pin_code" msgid="6535018036285012028">"தவறான பின் குறியீடு."</string>
     <string name="keyguard_sim_error_message_short" msgid="592109500618448312">"செல்லாத சிம் கார்டு."</string>
-    <string name="keyguard_charged" msgid="3316115607283493413">"முழுவதுமாகச் சார்ஜ் ஆகிவிட்டது"</string>
+    <string name="keyguard_charged" msgid="2222329688813033109">"சார்ஜ் செய்யப்பட்டது"</string>
     <string name="keyguard_plugged_in_wireless" msgid="8404159927155454732">"<xliff:g id="PERCENTAGE">%s</xliff:g> • வயர்லெஸ் முறையில் சார்ஜாகிறது"</string>
     <string name="keyguard_plugged_in" msgid="3161102098900158923">"<xliff:g id="PERCENTAGE">%s</xliff:g> • சார்ஜாகிறது"</string>
     <string name="keyguard_plugged_in_charging_fast" msgid="3684592786276709342">"<xliff:g id="PERCENTAGE">%s</xliff:g> • வேகமாகச் சார்ஜாகிறது"</string>
diff --git a/packages/SystemUI/res-keyguard/values-te/strings.xml b/packages/SystemUI/res-keyguard/values-te/strings.xml
index 925d673..ad89ba7 100644
--- a/packages/SystemUI/res-keyguard/values-te/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-te/strings.xml
@@ -33,7 +33,7 @@
     <string name="keyguard_enter_your_password" msgid="5397328359341314506">"మీ పాస్‌వర్డ్‌ను నమోదు చేయండి"</string>
     <string name="keyguard_password_wrong_pin_code" msgid="6535018036285012028">"పిన్ కోడ్ తప్పు."</string>
     <string name="keyguard_sim_error_message_short" msgid="592109500618448312">"చెల్లని కార్డ్."</string>
-    <string name="keyguard_charged" msgid="3316115607283493413">"పూర్తిగా ఛార్జ్ చేయబడింది"</string>
+    <string name="keyguard_charged" msgid="2222329688813033109">"ఛార్జ్ చేయబడింది"</string>
     <string name="keyguard_plugged_in_wireless" msgid="8404159927155454732">"<xliff:g id="PERCENTAGE">%s</xliff:g> • వైర్‌ లేకుండా ఛార్జ్ అవుతోంది"</string>
     <string name="keyguard_plugged_in" msgid="3161102098900158923">"<xliff:g id="PERCENTAGE">%s</xliff:g> • ఛార్జ్ అవుతోంది"</string>
     <string name="keyguard_plugged_in_charging_fast" msgid="3684592786276709342">"<xliff:g id="PERCENTAGE">%s</xliff:g> • వేగంగా ఛార్జ్ అవుతోంది"</string>
diff --git a/packages/SystemUI/res-keyguard/values-th/strings.xml b/packages/SystemUI/res-keyguard/values-th/strings.xml
index c439c32..caa60f3 100644
--- a/packages/SystemUI/res-keyguard/values-th/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-th/strings.xml
@@ -33,7 +33,7 @@
     <string name="keyguard_enter_your_password" msgid="5397328359341314506">"ป้อนรหัสผ่าน"</string>
     <string name="keyguard_password_wrong_pin_code" msgid="6535018036285012028">"รหัส PIN ไม่ถูกต้อง"</string>
     <string name="keyguard_sim_error_message_short" msgid="592109500618448312">"การ์ดไม่ถูกต้อง"</string>
-    <string name="keyguard_charged" msgid="3316115607283493413">"ชาร์จเต็มแล้ว"</string>
+    <string name="keyguard_charged" msgid="2222329688813033109">"ชาร์จแล้ว"</string>
     <string name="keyguard_plugged_in_wireless" msgid="8404159927155454732">"<xliff:g id="PERCENTAGE">%s</xliff:g> • กำลังชาร์จแบบไร้สาย"</string>
     <string name="keyguard_plugged_in" msgid="3161102098900158923">"<xliff:g id="PERCENTAGE">%s</xliff:g> • กำลังชาร์จ"</string>
     <string name="keyguard_plugged_in_charging_fast" msgid="3684592786276709342">"<xliff:g id="PERCENTAGE">%s</xliff:g> • กำลังชาร์จอย่างเร็ว"</string>
diff --git a/packages/SystemUI/res-keyguard/values-tl/strings.xml b/packages/SystemUI/res-keyguard/values-tl/strings.xml
index a9ca1b6..65b87e3 100644
--- a/packages/SystemUI/res-keyguard/values-tl/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-tl/strings.xml
@@ -33,7 +33,7 @@
     <string name="keyguard_enter_your_password" msgid="5397328359341314506">"Ilagay ang iyong password"</string>
     <string name="keyguard_password_wrong_pin_code" msgid="6535018036285012028">"Mali ang PIN code."</string>
     <string name="keyguard_sim_error_message_short" msgid="592109500618448312">"Di-wasto ang Card."</string>
-    <string name="keyguard_charged" msgid="3316115607283493413">"Puno na ang baterya"</string>
+    <string name="keyguard_charged" msgid="2222329688813033109">"Tapos nang mag-charge"</string>
     <string name="keyguard_plugged_in_wireless" msgid="8404159927155454732">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Wireless na nagcha-charge"</string>
     <string name="keyguard_plugged_in" msgid="3161102098900158923">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Nagcha-charge"</string>
     <string name="keyguard_plugged_in_charging_fast" msgid="3684592786276709342">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Mabilis na nagcha-charge"</string>
diff --git a/packages/SystemUI/res-keyguard/values-tr/strings.xml b/packages/SystemUI/res-keyguard/values-tr/strings.xml
index 4e81505..c35e99e 100644
--- a/packages/SystemUI/res-keyguard/values-tr/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-tr/strings.xml
@@ -33,7 +33,7 @@
     <string name="keyguard_enter_your_password" msgid="5397328359341314506">"Şifrenizi girin"</string>
     <string name="keyguard_password_wrong_pin_code" msgid="6535018036285012028">"Yanlış PIN kodu."</string>
     <string name="keyguard_sim_error_message_short" msgid="592109500618448312">"Geçersiz Kart."</string>
-    <string name="keyguard_charged" msgid="3316115607283493413">"Tamamen şarj edildi"</string>
+    <string name="keyguard_charged" msgid="2222329688813033109">"Şarj oldu"</string>
     <string name="keyguard_plugged_in_wireless" msgid="8404159927155454732">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Kablosuz olarak şarj ediliyor"</string>
     <string name="keyguard_plugged_in" msgid="3161102098900158923">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Şarj oluyor"</string>
     <string name="keyguard_plugged_in_charging_fast" msgid="3684592786276709342">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Hızlı şarj oluyor"</string>
diff --git a/packages/SystemUI/res-keyguard/values-uk/strings.xml b/packages/SystemUI/res-keyguard/values-uk/strings.xml
index c683e32..c2b9419 100644
--- a/packages/SystemUI/res-keyguard/values-uk/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-uk/strings.xml
@@ -33,7 +33,7 @@
     <string name="keyguard_enter_your_password" msgid="5397328359341314506">"Введіть пароль"</string>
     <string name="keyguard_password_wrong_pin_code" msgid="6535018036285012028">"Неправильний PIN-код."</string>
     <string name="keyguard_sim_error_message_short" msgid="592109500618448312">"Недійсна картка."</string>
-    <string name="keyguard_charged" msgid="3316115607283493413">"Повністю заряджений"</string>
+    <string name="keyguard_charged" msgid="2222329688813033109">"Заряджено"</string>
     <string name="keyguard_plugged_in_wireless" msgid="8404159927155454732">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Бездротове заряджання"</string>
     <string name="keyguard_plugged_in" msgid="3161102098900158923">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Заряджання"</string>
     <string name="keyguard_plugged_in_charging_fast" msgid="3684592786276709342">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Швидке заряджання"</string>
diff --git a/packages/SystemUI/res-keyguard/values-ur/strings.xml b/packages/SystemUI/res-keyguard/values-ur/strings.xml
index 96b949b..8a74093 100644
--- a/packages/SystemUI/res-keyguard/values-ur/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-ur/strings.xml
@@ -33,7 +33,7 @@
     <string name="keyguard_enter_your_password" msgid="5397328359341314506">"اپنا پاس ورڈ درج کریں"</string>
     <string name="keyguard_password_wrong_pin_code" msgid="6535018036285012028">"‏غلط PIN کوڈ۔"</string>
     <string name="keyguard_sim_error_message_short" msgid="592109500618448312">"غلط کارڈ۔"</string>
-    <string name="keyguard_charged" msgid="3316115607283493413">"مکمل طور پر چارج ہو گيا"</string>
+    <string name="keyguard_charged" msgid="2222329688813033109">"چارج ہوگئی"</string>
     <string name="keyguard_plugged_in_wireless" msgid="8404159927155454732">"<xliff:g id="PERCENTAGE">%s</xliff:g> • وائرلیس طریقے سے چارج ہو رہا ہے"</string>
     <string name="keyguard_plugged_in" msgid="3161102098900158923">"<xliff:g id="PERCENTAGE">%s</xliff:g> • چارج ہو رہا ہے"</string>
     <string name="keyguard_plugged_in_charging_fast" msgid="3684592786276709342">"<xliff:g id="PERCENTAGE">%s</xliff:g> • تیزی سے چارج ہو رہا ہے"</string>
diff --git a/packages/SystemUI/res-keyguard/values-uz/strings.xml b/packages/SystemUI/res-keyguard/values-uz/strings.xml
index 80509ac..5bf38ec 100644
--- a/packages/SystemUI/res-keyguard/values-uz/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-uz/strings.xml
@@ -33,9 +33,7 @@
     <string name="keyguard_enter_your_password" msgid="5397328359341314506">"Parolni kiriting"</string>
     <string name="keyguard_password_wrong_pin_code" msgid="6535018036285012028">"PIN kodi xato."</string>
     <string name="keyguard_sim_error_message_short" msgid="592109500618448312">"SIM karta yaroqsiz."</string>
-    <!-- String.format failed for translation -->
-    <!-- no translation found for keyguard_charged (3316115607283493413) -->
-    <skip />
+    <string name="keyguard_charged" msgid="2222329688813033109">"Batareya quvvati to‘ldi"</string>
     <string name="keyguard_plugged_in_wireless" msgid="8404159927155454732">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Simsiz quvvatlanyapti"</string>
     <string name="keyguard_plugged_in" msgid="3161102098900158923">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Quvvat olmoqda"</string>
     <string name="keyguard_plugged_in_charging_fast" msgid="3684592786276709342">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Tezkor quvvat olmoqda"</string>
diff --git a/packages/SystemUI/res-keyguard/values-vi/strings.xml b/packages/SystemUI/res-keyguard/values-vi/strings.xml
index b8c1998..c50891e 100644
--- a/packages/SystemUI/res-keyguard/values-vi/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-vi/strings.xml
@@ -33,7 +33,7 @@
     <string name="keyguard_enter_your_password" msgid="5397328359341314506">"Nhập mật khẩu của bạn"</string>
     <string name="keyguard_password_wrong_pin_code" msgid="6535018036285012028">"Mã PIN không chính xác."</string>
     <string name="keyguard_sim_error_message_short" msgid="592109500618448312">"Thẻ không hợp lệ."</string>
-    <string name="keyguard_charged" msgid="3316115607283493413">"Đã sạc đầy"</string>
+    <string name="keyguard_charged" msgid="2222329688813033109">"Đã sạc đầy"</string>
     <string name="keyguard_plugged_in_wireless" msgid="8404159927155454732">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Đang sạc không dây"</string>
     <string name="keyguard_plugged_in" msgid="3161102098900158923">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Đang sạc"</string>
     <string name="keyguard_plugged_in_charging_fast" msgid="3684592786276709342">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Đang sạc nhanh"</string>
diff --git a/packages/SystemUI/res-keyguard/values-zh-rCN/strings.xml b/packages/SystemUI/res-keyguard/values-zh-rCN/strings.xml
index 88fc363..e4438f9 100644
--- a/packages/SystemUI/res-keyguard/values-zh-rCN/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-zh-rCN/strings.xml
@@ -33,7 +33,7 @@
     <string name="keyguard_enter_your_password" msgid="5397328359341314506">"输入您的密码"</string>
     <string name="keyguard_password_wrong_pin_code" msgid="6535018036285012028">"PIN 码有误。"</string>
     <string name="keyguard_sim_error_message_short" msgid="592109500618448312">"SIM 卡无效。"</string>
-    <string name="keyguard_charged" msgid="3316115607283493413">"充电完成"</string>
+    <string name="keyguard_charged" msgid="2222329688813033109">"已充满电"</string>
     <string name="keyguard_plugged_in_wireless" msgid="8404159927155454732">"<xliff:g id="PERCENTAGE">%s</xliff:g> • 正在无线充电"</string>
     <string name="keyguard_plugged_in" msgid="3161102098900158923">"<xliff:g id="PERCENTAGE">%s</xliff:g> • 正在充电"</string>
     <string name="keyguard_plugged_in_charging_fast" msgid="3684592786276709342">"<xliff:g id="PERCENTAGE">%s</xliff:g> • 正在快速充电"</string>
diff --git a/packages/SystemUI/res-keyguard/values-zh-rHK/strings.xml b/packages/SystemUI/res-keyguard/values-zh-rHK/strings.xml
index 2d84106..4134527 100644
--- a/packages/SystemUI/res-keyguard/values-zh-rHK/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-zh-rHK/strings.xml
@@ -33,7 +33,7 @@
     <string name="keyguard_enter_your_password" msgid="5397328359341314506">"請輸入密碼"</string>
     <string name="keyguard_password_wrong_pin_code" msgid="6535018036285012028">"PIN 碼不正確。"</string>
     <string name="keyguard_sim_error_message_short" msgid="592109500618448312">"SIM 卡無效。"</string>
-    <string name="keyguard_charged" msgid="3316115607283493413">"充電完成"</string>
+    <string name="keyguard_charged" msgid="2222329688813033109">"已完成充電"</string>
     <string name="keyguard_plugged_in_wireless" msgid="8404159927155454732">"<xliff:g id="PERCENTAGE">%s</xliff:g> • 無線充電中"</string>
     <string name="keyguard_plugged_in" msgid="3161102098900158923">"<xliff:g id="PERCENTAGE">%s</xliff:g> • 正在充電"</string>
     <string name="keyguard_plugged_in_charging_fast" msgid="3684592786276709342">"<xliff:g id="PERCENTAGE">%s</xliff:g> • 正在快速充電"</string>
diff --git a/packages/SystemUI/res-keyguard/values-zh-rTW/strings.xml b/packages/SystemUI/res-keyguard/values-zh-rTW/strings.xml
index 18b9479..fd95559 100644
--- a/packages/SystemUI/res-keyguard/values-zh-rTW/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-zh-rTW/strings.xml
@@ -33,7 +33,7 @@
     <string name="keyguard_enter_your_password" msgid="5397328359341314506">"輸入密碼"</string>
     <string name="keyguard_password_wrong_pin_code" msgid="6535018036285012028">"PIN 碼不正確。"</string>
     <string name="keyguard_sim_error_message_short" msgid="592109500618448312">"卡片無效。"</string>
-    <string name="keyguard_charged" msgid="3316115607283493413">"充電完成"</string>
+    <string name="keyguard_charged" msgid="2222329688813033109">"充電完成"</string>
     <string name="keyguard_plugged_in_wireless" msgid="8404159927155454732">"<xliff:g id="PERCENTAGE">%s</xliff:g> • 無線充電"</string>
     <string name="keyguard_plugged_in" msgid="3161102098900158923">"<xliff:g id="PERCENTAGE">%s</xliff:g> • 充電中"</string>
     <string name="keyguard_plugged_in_charging_fast" msgid="3684592786276709342">"<xliff:g id="PERCENTAGE">%s</xliff:g> • 快速充電中"</string>
diff --git a/packages/SystemUI/res-keyguard/values-zu/strings.xml b/packages/SystemUI/res-keyguard/values-zu/strings.xml
index 6a7f647..f60599d 100644
--- a/packages/SystemUI/res-keyguard/values-zu/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-zu/strings.xml
@@ -33,7 +33,7 @@
     <string name="keyguard_enter_your_password" msgid="5397328359341314506">"Faka iphasiwedi yakho"</string>
     <string name="keyguard_password_wrong_pin_code" msgid="6535018036285012028">"Ikhodi ye-PIN engalungile!"</string>
     <string name="keyguard_sim_error_message_short" msgid="592109500618448312">"Ikhadi elingavumelekile."</string>
-    <string name="keyguard_charged" msgid="3316115607283493413">"Ishaje ngokuphelele"</string>
+    <string name="keyguard_charged" msgid="2222329688813033109">"Kushajiwe"</string>
     <string name="keyguard_plugged_in_wireless" msgid="8404159927155454732">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Iyashaja ngaphandle kwentambo"</string>
     <string name="keyguard_plugged_in" msgid="3161102098900158923">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Iyashaja"</string>
     <string name="keyguard_plugged_in_charging_fast" msgid="3684592786276709342">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Ishaja kaningi"</string>
diff --git a/packages/SystemUI/res/drawable/auth_dialog_lock.xml b/packages/SystemUI/res/drawable/auth_dialog_lock.xml
new file mode 100644
index 0000000..8146c16
--- /dev/null
+++ b/packages/SystemUI/res/drawable/auth_dialog_lock.xml
@@ -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.
+  -->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+    android:width="32dp"
+    android:height="32dp"
+    android:viewportWidth="24"
+    android:viewportHeight="24">
+    <path
+        android:fillColor="?android:attr/colorAccent"
+        android:pathData="M12,15m-2,0a2,2 0,1 1,4 0a2,2 0,1 1,-4 0"/>
+    <path
+        android:fillColor="?android:attr/colorAccent"
+        android:pathData="M18,8h-1.5V5.5C16.5,3.01 14.49,1 12,1S7.5,3.01 7.5,5.5V8H6c-1.1,0 -2,0.9 -2,2v10c0,1.1 0.9,2 2,2h12c1.1,0 2,-0.9 2,-2V10C20,8.9 19.1,8 18,8zM9.5,5.5C9.5,4.12 10.62,3 12,3c1.38,0 2.5,1.12 2.5,2.5V8h-5V5.5zM18,20H6V10h1.5h9H18V20z"/>
+</vector>
diff --git a/packages/SystemUI/res/layout-land/auth_credential_pattern_view.xml b/packages/SystemUI/res/layout-land/auth_credential_pattern_view.xml
new file mode 100644
index 0000000..c3fa39e
--- /dev/null
+++ b/packages/SystemUI/res/layout-land/auth_credential_pattern_view.xml
@@ -0,0 +1,113 @@
+<!--
+  ~ 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.biometrics.AuthCredentialPatternView
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent"
+    android:orientation="horizontal"
+    android:elevation="@dimen/biometric_dialog_elevation">
+
+    <LinearLayout
+        android:layout_width="0dp"
+        android:layout_height="match_parent"
+        android:layout_weight="1"
+        android:gravity="center"
+        android:orientation="vertical">
+
+        <Space
+            android:layout_width="0dp"
+            android:layout_height="0dp"
+            android:layout_weight="1"/>
+
+        <ImageView
+            android:layout_width="32dp"
+            android:layout_height="32dp"
+            android:background="@drawable/auth_dialog_lock"/>
+
+        <TextView
+            android:id="@+id/title"
+            android:fontFamily="@*android:string/config_headlineFontFamilyMedium"
+            android:layout_width="match_parent"
+            android:layout_height="wrap_content"
+            android:layout_marginHorizontal="24dp"
+            android:layout_marginTop="12dp"
+            android:textSize="20sp"
+            android:gravity="center"
+            android:textColor="?android:attr/textColorPrimary"/>
+
+        <TextView
+            android:id="@+id/subtitle"
+            android:layout_width="match_parent"
+            android:layout_height="wrap_content"
+            android:layout_marginHorizontal="24dp"
+            android:layout_marginTop="8dp"
+            android:textSize="16sp"
+            android:gravity="center"
+            android:textColor="?android:attr/textColorPrimary"/>
+
+        <TextView
+            android:id="@+id/description"
+            android:layout_width="match_parent"
+            android:layout_height="wrap_content"
+            android:layout_marginHorizontal="24dp"
+            android:layout_marginTop="8dp"
+            android:gravity="center"
+            android:textSize="16sp"
+            android:textColor="?android:attr/textColorPrimary"/>
+
+        <Space
+            android:layout_width="0dp"
+            android:layout_height="0dp"
+            android:layout_weight="1"/>
+
+        <TextView
+            android:id="@+id/error"
+            android:layout_width="match_parent"
+            android:layout_height="wrap_content"
+            android:layout_marginHorizontal="24dp"
+            android:textSize="16sp"
+            android:gravity="center"
+            android:textColor="?android:attr/colorError"/>
+
+        <Space
+            android:layout_width="0dp"
+            android:layout_height="0dp"
+            android:layout_weight="1"/>
+
+    </LinearLayout>
+
+    <LinearLayout
+        android:layout_width="0dp"
+        android:layout_height="match_parent"
+        android:layout_weight="1"
+        android:orientation="vertical"
+        android:gravity="center">
+
+        <com.android.internal.widget.LockPatternView
+            android:id="@+id/lockPattern"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:layout_marginLeft="40dp"
+            android:layout_marginRight="40dp"
+            android:layout_gravity="center"
+            android:clipChildren="false"
+            android:clipToPadding="false"
+            style="@style/LockPatternStyleBiometricPrompt"/>
+
+    </LinearLayout>
+
+</com.android.systemui.biometrics.AuthCredentialPatternView>
\ No newline at end of file
diff --git a/packages/SystemUI/res/layout/auth_container_view.xml b/packages/SystemUI/res/layout/auth_container_view.xml
index 23199aa..3db01a4 100644
--- a/packages/SystemUI/res/layout/auth_container_view.xml
+++ b/packages/SystemUI/res/layout/auth_container_view.xml
@@ -34,7 +34,7 @@
         android:elevation="@dimen/biometric_dialog_elevation"/>
 
     <ScrollView
-        android:id="@+id/scrollview"
+        android:id="@+id/biometric_scrollview"
         android:layout_width="wrap_content"
         android:layout_height="wrap_content"
         android:layout_gravity="center_horizontal|bottom"
diff --git a/packages/SystemUI/res/layout/auth_credential_password_view.xml b/packages/SystemUI/res/layout/auth_credential_password_view.xml
new file mode 100644
index 0000000..4aed033
--- /dev/null
+++ b/packages/SystemUI/res/layout/auth_credential_password_view.xml
@@ -0,0 +1,101 @@
+<!--
+  ~ 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.biometrics.AuthCredentialPasswordView
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent"
+    android:orientation="vertical"
+    android:gravity="center_horizontal"
+    android:elevation="@dimen/biometric_dialog_elevation">
+
+    <Space
+        android:layout_width="0dp"
+        android:layout_height="0dp"
+        android:layout_weight="1"/>
+
+    <ImageView
+        android:layout_width="32dp"
+        android:layout_height="32dp"
+        android:background="@drawable/auth_dialog_lock"/>
+
+    <TextView
+        android:id="@+id/title"
+        android:fontFamily="@*android:string/config_headlineFontFamilyMedium"
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:layout_marginHorizontal="24dp"
+        android:layout_marginTop="12dp"
+        android:textSize="20sp"
+        android:gravity="center"
+        android:textColor="?android:attr/textColorPrimary"/>
+
+    <TextView
+        android:id="@+id/subtitle"
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:layout_marginHorizontal="24dp"
+        android:layout_marginTop="8dp"
+        android:textSize="16sp"
+        android:gravity="center"
+        android:textColor="?android:attr/textColorPrimary"/>
+
+    <TextView
+        android:id="@+id/description"
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:layout_marginHorizontal="24dp"
+        android:layout_marginTop="8dp"
+        android:gravity="center"
+        android:textSize="16sp"
+        android:textColor="?android:attr/textColorPrimary"/>
+
+    <Space
+        android:layout_width="0dp"
+        android:layout_height="0dp"
+        android:layout_weight="1"/>
+
+    <TextView
+        android:id="@+id/error"
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:layout_marginHorizontal="24dp"
+        android:textSize="16sp"
+        android:gravity="center"
+        android:textColor="?android:attr/colorError"/>
+
+    <EditText
+        android:id="@+id/lockPassword"
+        android:layout_marginBottom="20dp"
+        android:layout_marginLeft="100dp"
+        android:layout_marginRight="100dp"
+        android:layout_width="208dp"
+        android:layout_height="wrap_content"
+        android:layout_gravity="center"
+        android:gravity="center"
+        android:inputType="textPassword"
+        android:maxLength="500"
+        android:textSize="16sp"
+        android:textAppearance="?android:attr/textAppearanceMedium"
+        android:imeOptions="flagForceAscii"
+        style="@style/LockPatternStyleBiometricPrompt"/>
+
+    <Space
+        android:layout_width="0dp"
+        android:layout_height="0dp"
+        android:layout_weight="5"/>
+
+</com.android.systemui.biometrics.AuthCredentialPasswordView>
\ No newline at end of file
diff --git a/packages/SystemUI/res/layout/auth_credential_pattern_view.xml b/packages/SystemUI/res/layout/auth_credential_pattern_view.xml
new file mode 100644
index 0000000..c9edcd6
--- /dev/null
+++ b/packages/SystemUI/res/layout/auth_credential_pattern_view.xml
@@ -0,0 +1,97 @@
+<!--
+  ~ 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.biometrics.AuthCredentialPatternView
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent"
+    android:orientation="vertical"
+    android:gravity="center_horizontal"
+    android:elevation="@dimen/biometric_dialog_elevation">
+
+    <Space
+        android:layout_width="0dp"
+        android:layout_height="0dp"
+        android:layout_weight="1"/>
+
+    <ImageView
+        android:layout_width="32dp"
+        android:layout_height="32dp"
+        android:background="@drawable/auth_dialog_lock"/>
+
+    <TextView
+        android:id="@+id/title"
+        android:fontFamily="@*android:string/config_headlineFontFamilyMedium"
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:layout_marginHorizontal="24dp"
+        android:layout_marginTop="12dp"
+        android:textSize="20sp"
+        android:gravity="center"
+        android:textColor="?android:attr/textColorPrimary"/>
+
+    <TextView
+        android:id="@+id/subtitle"
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:layout_marginHorizontal="24dp"
+        android:layout_marginTop="8dp"
+        android:textSize="16sp"
+        android:gravity="center"
+        android:textColor="?android:attr/textColorPrimary"/>
+
+    <TextView
+        android:id="@+id/description"
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:layout_marginHorizontal="24dp"
+        android:layout_marginTop="8dp"
+        android:gravity="center"
+        android:textSize="16sp"
+        android:textColor="?android:attr/textColorPrimary"/>
+
+    <Space
+        android:layout_width="0dp"
+        android:layout_height="0dp"
+        android:layout_weight="3"/>
+
+    <TextView
+        android:id="@+id/error"
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:layout_marginHorizontal="24dp"
+        android:textSize="16sp"
+        android:gravity="center"
+        android:textColor="?android:attr/colorError"/>
+
+    <com.android.internal.widget.LockPatternView
+        android:id="@+id/lockPattern"
+        android:layout_marginBottom="20dp"
+        android:layout_marginLeft="40dp"
+        android:layout_marginRight="40dp"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:layout_gravity="center"
+        android:clipChildren="false"
+        android:clipToPadding="false"
+        style="@style/LockPatternStyleBiometricPrompt"/>
+
+    <Space
+        android:layout_width="0dp"
+        android:layout_height="0dp"
+        android:layout_weight="1"/>
+
+</com.android.systemui.biometrics.AuthCredentialPatternView>
\ No newline at end of file
diff --git a/packages/SystemUI/res/layout/status_bar_expanded.xml b/packages/SystemUI/res/layout/status_bar_expanded.xml
index e7c6b25..0e59a41 100644
--- a/packages/SystemUI/res/layout/status_bar_expanded.xml
+++ b/packages/SystemUI/res/layout/status_bar_expanded.xml
@@ -17,14 +17,9 @@
 */
 -->
 
-<com.android.systemui.statusbar.phone.NotificationPanelView
+<merge
     xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:systemui="http://schemas.android.com/apk/res-auto"
-    android:id="@+id/notification_panel"
-    android:layout_width="match_parent"
-    android:layout_height="match_parent"
-    android:background="@android:color/transparent" >
-
+    xmlns:systemui="http://schemas.android.com/apk/res-auto">
     <FrameLayout
         android:id="@+id/big_clock_container"
         android:layout_width="match_parent"
@@ -112,5 +107,4 @@
         android:background="@drawable/qs_navbar_scrim" />
 
     <include layout="@layout/status_bar_expanded_plugin_frame"/>
-
-</com.android.systemui.statusbar.phone.NotificationPanelView>
+</merge>
\ No newline at end of file
diff --git a/packages/SystemUI/res/layout/super_status_bar.xml b/packages/SystemUI/res/layout/super_status_bar.xml
index 9716a00..57834da 100644
--- a/packages/SystemUI/res/layout/super_status_bar.xml
+++ b/packages/SystemUI/res/layout/super_status_bar.xml
@@ -64,7 +64,7 @@
         sysui:ignoreRightInset="true"
         />
 
-    <include layout="@layout/status_bar_expanded"
+    <ViewStub android:id="@+id/status_bar_expanded"
         android:layout_width="match_parent"
         android:layout_height="match_parent"
         android:visibility="invisible" />
diff --git a/packages/SystemUI/res/values-af/strings.xml b/packages/SystemUI/res/values-af/strings.xml
index 4d451bc..b0b4615 100644
--- a/packages/SystemUI/res/values-af/strings.xml
+++ b/packages/SystemUI/res/values-af/strings.xml
@@ -47,6 +47,8 @@
     <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_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_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>
@@ -126,6 +128,20 @@
     <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="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>
@@ -364,6 +380,8 @@
     </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_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 4d0a62e..e423c6a 100644
--- a/packages/SystemUI/res/values-am/strings.xml
+++ b/packages/SystemUI/res/values-am/strings.xml
@@ -47,6 +47,8 @@
     <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_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_accessory_confirm_prompt" msgid="4333670517539993561">"<xliff:g id="USB_ACCESSORY">%2$s</xliff:g>ን እንዲይዘው <xliff:g id="APPLICATION">%1$s</xliff:g> ይክፈት?"</string>
@@ -108,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>
@@ -126,6 +128,20 @@
     <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="face_dialog_looking_for_face" msgid="7049276266074494689">"እርስዎን በመፈለግ ላይ…"</string>
@@ -364,6 +380,8 @@
     </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_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 787fc8d..3b145105 100644
--- a/packages/SystemUI/res/values-ar/strings.xml
+++ b/packages/SystemUI/res/values-ar/strings.xml
@@ -47,6 +47,8 @@
     <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_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_accessory_confirm_prompt" msgid="4333670517539993561">"هل تريد فتح تطبيق <xliff:g id="APPLICATION">%1$s</xliff:g> للتعامل مع <xliff:g id="USB_ACCESSORY">%2$s</xliff:g>؟"</string>
@@ -126,6 +128,20 @@
     <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="face_dialog_looking_for_face" msgid="7049276266074494689">"جارٍ البحث عن وجهك…"</string>
@@ -372,6 +388,8 @@
     </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_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 d7feb0c..c3ca88a 100644
--- a/packages/SystemUI/res/values-as/strings.xml
+++ b/packages/SystemUI/res/values-as/strings.xml
@@ -47,6 +47,8 @@
     <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_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_accessory_confirm_prompt" msgid="4333670517539993561">"<xliff:g id="USB_ACCESSORY">%2$s</xliff:g>ক ব্যৱহাৰ কৰিবলৈ <xliff:g id="APPLICATION">%1$s</xliff:g>ক খোলেনে?"</string>
@@ -126,6 +128,20 @@
     <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="face_dialog_looking_for_face" msgid="7049276266074494689">"আপোনাৰ মুখমণ্ডল বিচাৰি আছে…"</string>
@@ -364,6 +380,8 @@
     </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_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 f6cd5dc..67e24c5 100644
--- a/packages/SystemUI/res/values-az/strings.xml
+++ b/packages/SystemUI/res/values-az/strings.xml
@@ -47,6 +47,8 @@
     <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_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_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>
@@ -126,6 +128,20 @@
     <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="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>
@@ -364,6 +380,8 @@
     </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_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 2196c15..3def744 100644
--- a/packages/SystemUI/res/values-b+sr+Latn/strings.xml
+++ b/packages/SystemUI/res/values-b+sr+Latn/strings.xml
@@ -47,6 +47,8 @@
     <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_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_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>
@@ -126,6 +128,20 @@
     <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="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>
@@ -366,6 +382,8 @@
     </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_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 06ee3e1..cdb4ddb 100644
--- a/packages/SystemUI/res/values-be/strings.xml
+++ b/packages/SystemUI/res/values-be/strings.xml
@@ -47,6 +47,8 @@
     <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_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_accessory_confirm_prompt" msgid="4333670517539993561">"Адкрыць праграму <xliff:g id="APPLICATION">%1$s</xliff:g> для працы з прыладай <xliff:g id="USB_ACCESSORY">%2$s</xliff:g>?"</string>
@@ -126,6 +128,20 @@
     <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="face_dialog_looking_for_face" msgid="7049276266074494689">"Ідзе пошук вашага твару…"</string>
@@ -370,6 +386,8 @@
     </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_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 6f37a75..cd22290 100644
--- a/packages/SystemUI/res/values-bg/strings.xml
+++ b/packages/SystemUI/res/values-bg/strings.xml
@@ -47,6 +47,8 @@
     <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_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_accessory_confirm_prompt" msgid="4333670517539993561">"Да се използва ли <xliff:g id="APPLICATION">%1$s</xliff:g> за работата с/ъс <xliff:g id="USB_ACCESSORY">%2$s</xliff:g>?"</string>
@@ -126,6 +128,20 @@
     <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="face_dialog_looking_for_face" msgid="7049276266074494689">"Търсим ви…"</string>
@@ -364,6 +380,8 @@
     </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_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 9c33f2b..11a6e90 100644
--- a/packages/SystemUI/res/values-bn/strings.xml
+++ b/packages/SystemUI/res/values-bn/strings.xml
@@ -47,6 +47,8 @@
     <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_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_accessory_confirm_prompt" msgid="4333670517539993561">"<xliff:g id="USB_ACCESSORY">%2$s</xliff:g> ব্যবহার করার জন্য <xliff:g id="APPLICATION">%1$s</xliff:g> চালু করবেন?"</string>
@@ -126,6 +128,20 @@
     <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="face_dialog_looking_for_face" msgid="7049276266074494689">"আপনার জন্য খোঁজা হচ্ছে…"</string>
@@ -364,6 +380,8 @@
     </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_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 2d77626..7eaa9c4 100644
--- a/packages/SystemUI/res/values-bs/strings.xml
+++ b/packages/SystemUI/res/values-bs/strings.xml
@@ -47,6 +47,8 @@
     <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_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_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>
@@ -126,6 +128,20 @@
     <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="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>
@@ -366,6 +382,8 @@
     </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_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>
diff --git a/packages/SystemUI/res/values-ca/strings.xml b/packages/SystemUI/res/values-ca/strings.xml
index ee16c58..3bd72b3 100644
--- a/packages/SystemUI/res/values-ca/strings.xml
+++ b/packages/SystemUI/res/values-ca/strings.xml
@@ -47,6 +47,8 @@
     <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_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>
     <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>
@@ -126,6 +128,20 @@
     <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="face_dialog_looking_for_face" msgid="7049276266074494689">"S\'està cercant la teva cara…"</string>
@@ -364,6 +380,8 @@
     </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_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>
diff --git a/packages/SystemUI/res/values-cs/strings.xml b/packages/SystemUI/res/values-cs/strings.xml
index bed63db..b3a8596 100644
--- a/packages/SystemUI/res/values-cs/strings.xml
+++ b/packages/SystemUI/res/values-cs/strings.xml
@@ -47,6 +47,8 @@
     <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_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_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>
@@ -126,6 +128,20 @@
     <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="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>
@@ -368,6 +384,8 @@
     </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_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 45ef5b1..f0e5898 100644
--- a/packages/SystemUI/res/values-da/strings.xml
+++ b/packages/SystemUI/res/values-da/strings.xml
@@ -47,6 +47,8 @@
     <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_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_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>
@@ -126,6 +128,20 @@
     <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="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>
@@ -364,6 +380,8 @@
     </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_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 1deceb1..f32c577 100644
--- a/packages/SystemUI/res/values-de/strings.xml
+++ b/packages/SystemUI/res/values-de/strings.xml
@@ -47,6 +47,8 @@
     <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_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_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>
@@ -126,6 +128,20 @@
     <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="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>
@@ -368,6 +384,8 @@
     </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_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 2b57ab5..ce693ee 100644
--- a/packages/SystemUI/res/values-el/strings.xml
+++ b/packages/SystemUI/res/values-el/strings.xml
@@ -47,6 +47,8 @@
     <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_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_accessory_confirm_prompt" msgid="4333670517539993561">"Να ανοίγει η εφαρμογή <xliff:g id="APPLICATION">%1$s</xliff:g> για τη διαχείριση του αξεσουάρ <xliff:g id="USB_ACCESSORY">%2$s</xliff:g>;"</string>
@@ -126,6 +128,20 @@
     <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="face_dialog_looking_for_face" msgid="7049276266074494689">"Αναζήτηση για εσάς…"</string>
@@ -364,6 +380,8 @@
     </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_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 7a6271f..013b4cb 100644
--- a/packages/SystemUI/res/values-en-rAU/strings.xml
+++ b/packages/SystemUI/res/values-en-rAU/strings.xml
@@ -47,6 +47,7 @@
     <string name="status_bar_input_method_settings_configure_input_methods" msgid="3504292471512317827">"Set up input methods"</string>
     <string name="status_bar_use_physical_keyboard" msgid="7551903084416057810">"Physical keyboard"</string>
     <string name="usb_device_permission_prompt" msgid="1825685909587559679">"Allow <xliff:g id="APPLICATION">%1$s</xliff:g> to access <xliff:g id="USB_DEVICE">%2$s</xliff:g>?"</string>
+    <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_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>
@@ -126,6 +127,20 @@
     <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="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>
@@ -364,6 +379,7 @@
     </plurals>
     <string name="quick_settings_notifications_label" msgid="4818156442169154523">"Notifications"</string>
     <string name="quick_settings_flashlight_label" msgid="2133093497691661546">"Torch"</string>
+    <string name="quick_settings_flashlight_camera_in_use" msgid="6120370795890963385">"Camera in use"</string>
     <string name="quick_settings_cellular_detail_title" msgid="3661194685666477347">"Mobile data"</string>
     <string name="quick_settings_cellular_detail_data_usage" msgid="1964260360259312002">"Data usage"</string>
     <string name="quick_settings_cellular_detail_remaining_data" msgid="722715415543541249">"Remaining data"</string>
diff --git a/packages/SystemUI/res/values-en-rCA/strings.xml b/packages/SystemUI/res/values-en-rCA/strings.xml
index fe19e7c..a21ecb49 100644
--- a/packages/SystemUI/res/values-en-rCA/strings.xml
+++ b/packages/SystemUI/res/values-en-rCA/strings.xml
@@ -47,6 +47,7 @@
     <string name="status_bar_input_method_settings_configure_input_methods" msgid="3504292471512317827">"Set up input methods"</string>
     <string name="status_bar_use_physical_keyboard" msgid="7551903084416057810">"Physical keyboard"</string>
     <string name="usb_device_permission_prompt" msgid="1825685909587559679">"Allow <xliff:g id="APPLICATION">%1$s</xliff:g> to access <xliff:g id="USB_DEVICE">%2$s</xliff:g>?"</string>
+    <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_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>
@@ -126,6 +127,20 @@
     <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="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>
@@ -364,6 +379,7 @@
     </plurals>
     <string name="quick_settings_notifications_label" msgid="4818156442169154523">"Notifications"</string>
     <string name="quick_settings_flashlight_label" msgid="2133093497691661546">"Flashlight"</string>
+    <string name="quick_settings_flashlight_camera_in_use" msgid="6120370795890963385">"Camera in use"</string>
     <string name="quick_settings_cellular_detail_title" msgid="3661194685666477347">"Mobile data"</string>
     <string name="quick_settings_cellular_detail_data_usage" msgid="1964260360259312002">"Data usage"</string>
     <string name="quick_settings_cellular_detail_remaining_data" msgid="722715415543541249">"Remaining data"</string>
diff --git a/packages/SystemUI/res/values-en-rGB/strings.xml b/packages/SystemUI/res/values-en-rGB/strings.xml
index 7a6271f..013b4cb 100644
--- a/packages/SystemUI/res/values-en-rGB/strings.xml
+++ b/packages/SystemUI/res/values-en-rGB/strings.xml
@@ -47,6 +47,7 @@
     <string name="status_bar_input_method_settings_configure_input_methods" msgid="3504292471512317827">"Set up input methods"</string>
     <string name="status_bar_use_physical_keyboard" msgid="7551903084416057810">"Physical keyboard"</string>
     <string name="usb_device_permission_prompt" msgid="1825685909587559679">"Allow <xliff:g id="APPLICATION">%1$s</xliff:g> to access <xliff:g id="USB_DEVICE">%2$s</xliff:g>?"</string>
+    <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_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>
@@ -126,6 +127,20 @@
     <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="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>
@@ -364,6 +379,7 @@
     </plurals>
     <string name="quick_settings_notifications_label" msgid="4818156442169154523">"Notifications"</string>
     <string name="quick_settings_flashlight_label" msgid="2133093497691661546">"Torch"</string>
+    <string name="quick_settings_flashlight_camera_in_use" msgid="6120370795890963385">"Camera in use"</string>
     <string name="quick_settings_cellular_detail_title" msgid="3661194685666477347">"Mobile data"</string>
     <string name="quick_settings_cellular_detail_data_usage" msgid="1964260360259312002">"Data usage"</string>
     <string name="quick_settings_cellular_detail_remaining_data" msgid="722715415543541249">"Remaining data"</string>
diff --git a/packages/SystemUI/res/values-en-rIN/strings.xml b/packages/SystemUI/res/values-en-rIN/strings.xml
index 7a6271f..013b4cb 100644
--- a/packages/SystemUI/res/values-en-rIN/strings.xml
+++ b/packages/SystemUI/res/values-en-rIN/strings.xml
@@ -47,6 +47,7 @@
     <string name="status_bar_input_method_settings_configure_input_methods" msgid="3504292471512317827">"Set up input methods"</string>
     <string name="status_bar_use_physical_keyboard" msgid="7551903084416057810">"Physical keyboard"</string>
     <string name="usb_device_permission_prompt" msgid="1825685909587559679">"Allow <xliff:g id="APPLICATION">%1$s</xliff:g> to access <xliff:g id="USB_DEVICE">%2$s</xliff:g>?"</string>
+    <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_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>
@@ -126,6 +127,20 @@
     <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="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>
@@ -364,6 +379,7 @@
     </plurals>
     <string name="quick_settings_notifications_label" msgid="4818156442169154523">"Notifications"</string>
     <string name="quick_settings_flashlight_label" msgid="2133093497691661546">"Torch"</string>
+    <string name="quick_settings_flashlight_camera_in_use" msgid="6120370795890963385">"Camera in use"</string>
     <string name="quick_settings_cellular_detail_title" msgid="3661194685666477347">"Mobile data"</string>
     <string name="quick_settings_cellular_detail_data_usage" msgid="1964260360259312002">"Data usage"</string>
     <string name="quick_settings_cellular_detail_remaining_data" msgid="722715415543541249">"Remaining data"</string>
diff --git a/packages/SystemUI/res/values-en-rXC/strings.xml b/packages/SystemUI/res/values-en-rXC/strings.xml
index 32469f2..d8cfb30 100644
--- a/packages/SystemUI/res/values-en-rXC/strings.xml
+++ b/packages/SystemUI/res/values-en-rXC/strings.xml
@@ -47,6 +47,7 @@
     <string name="status_bar_input_method_settings_configure_input_methods" msgid="3504292471512317827">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‏‎‎‎‎‏‎‏‎‎‎‎‏‏‎‏‏‏‏‏‏‎‏‏‎‏‏‏‏‏‎‏‏‎‎‎‏‏‎‎‏‎‎‎‏‎‎‏‏‏‏‏‏‏‎‎‎‎‎‏‏‎Set up input methods‎‏‎‎‏‎"</string>
     <string name="status_bar_use_physical_keyboard" msgid="7551903084416057810">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‎‏‎‎‎‏‏‎‎‏‏‎‏‏‎‏‏‏‏‏‏‏‏‎‏‎‏‏‏‏‏‏‏‎‏‎‎‏‏‎‎‏‎‏‏‏‏‎‎‎‎‎‏‏‏‎‏‎‎‏‎‎Physical keyboard‎‏‎‎‏‎"</string>
     <string name="usb_device_permission_prompt" msgid="1825685909587559679">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‎‏‏‏‎‎‏‎‏‎‏‎‏‏‎‎‎‏‎‎‎‏‏‏‎‏‎‏‎‎‏‎‏‏‏‎‎‎‎‎‏‏‎‎‏‏‏‎‎‎‎‎‏‎‎‏‏‏‏‏‏‏‏‎Allow ‎‏‎‎‏‏‎<xliff:g id="APPLICATION">%1$s</xliff:g>‎‏‎‎‏‏‏‎ to access ‎‏‎‎‏‏‎<xliff:g id="USB_DEVICE">%2$s</xliff:g>‎‏‎‎‏‏‏‎?‎‏‎‎‏‎"</string>
+    <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_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>
@@ -126,6 +127,20 @@
     <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="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>
@@ -364,6 +379,7 @@
     </plurals>
     <string name="quick_settings_notifications_label" msgid="4818156442169154523">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‎‎‎‏‎‏‏‎‏‏‏‎‏‏‎‎‎‎‏‏‏‏‏‎‎‎‎‎‏‏‎‏‎‎‏‏‏‏‏‎‎‎‎‎‎‏‎‎‏‏‎‏‏‏‏‎‏‏‎‏‏‎Notifications‎‏‎‎‏‎"</string>
     <string name="quick_settings_flashlight_label" msgid="2133093497691661546">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‎‏‏‏‏‎‏‏‎‎‏‏‎‏‎‎‏‎‎‎‏‎‏‎‎‏‏‏‏‎‎‎‎‎‎‏‎‏‎‏‎‎‏‏‎‏‏‎‏‏‎‎‏‎‎‏‏‏‎‏‎‏‎‎Flashlight‎‏‎‎‏‎"</string>
+    <string name="quick_settings_flashlight_camera_in_use" msgid="6120370795890963385">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‏‎‏‎‎‏‏‏‎‏‏‏‏‏‏‏‎‏‏‎‎‏‏‎‎‏‏‏‏‏‏‎‎‏‏‏‎‏‏‎‎‎‎‎‏‎‏‏‏‎‎‏‏‏‎‏‏‏‎‎‏‎Camera in use‎‏‎‎‏‎"</string>
     <string name="quick_settings_cellular_detail_title" msgid="3661194685666477347">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‏‎‎‏‎‏‏‎‎‏‏‏‏‎‎‏‎‏‏‎‏‎‎‏‎‏‎‏‏‎‎‏‏‎‏‎‎‏‎‏‏‎‎‏‎‏‏‎‎‎‏‎‏‎‎‏‎‎‎‏‏‎Mobile data‎‏‎‎‏‎"</string>
     <string name="quick_settings_cellular_detail_data_usage" msgid="1964260360259312002">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‎‏‏‏‎‏‏‎‏‎‎‎‎‏‎‎‏‏‏‎‏‎‎‎‏‏‎‎‎‏‏‏‏‏‏‏‎‏‏‏‎‏‎‎‎‏‏‎‎‎‏‏‎‎‏‏‎‎‎‎‎‏‎‎Data usage‎‏‎‎‏‎"</string>
     <string name="quick_settings_cellular_detail_remaining_data" msgid="722715415543541249">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‎‎‏‎‏‎‎‎‎‎‎‏‏‏‏‎‎‏‏‎‎‏‏‏‎‏‎‏‏‏‎‏‏‎‎‎‎‏‎‎‏‎‏‎‏‏‏‏‏‎‏‏‏‎‎‎‎‎‎‎‎‏‎Remaining data‎‏‎‎‏‎"</string>
diff --git a/packages/SystemUI/res/values-es-rUS/strings.xml b/packages/SystemUI/res/values-es-rUS/strings.xml
index f29aa1e..4b2943c 100644
--- a/packages/SystemUI/res/values-es-rUS/strings.xml
+++ b/packages/SystemUI/res/values-es-rUS/strings.xml
@@ -47,6 +47,8 @@
     <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_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_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>
@@ -126,6 +128,20 @@
     <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="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>
@@ -364,6 +380,8 @@
     </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_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 3088098..903c50a 100644
--- a/packages/SystemUI/res/values-es/strings.xml
+++ b/packages/SystemUI/res/values-es/strings.xml
@@ -47,6 +47,8 @@
     <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_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>
     <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>
@@ -126,6 +128,20 @@
     <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="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>
@@ -364,6 +380,8 @@
     </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_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 51226ab..113b207 100644
--- a/packages/SystemUI/res/values-et/strings.xml
+++ b/packages/SystemUI/res/values-et/strings.xml
@@ -47,6 +47,8 @@
     <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_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_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>
@@ -126,6 +128,20 @@
     <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="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>
@@ -364,6 +380,8 @@
     </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_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 0d2863e..e541329 100644
--- a/packages/SystemUI/res/values-eu/strings.xml
+++ b/packages/SystemUI/res/values-eu/strings.xml
@@ -47,6 +47,8 @@
     <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_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_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>
@@ -126,6 +128,20 @@
     <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="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>
@@ -364,6 +380,8 @@
     </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_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>
@@ -897,7 +915,7 @@
     <string name="mobile_data_disable_message" msgid="4756541658791493506">"<xliff:g id="CARRIER">%s</xliff:g> erabilita ezingo dituzu erabili datuak edo Internet. Wifi-sare baten bidez soilik konektatu ahal izango zara Internetera."</string>
     <string name="mobile_data_disable_message_default_carrier" msgid="6078110473451946831">"Uneko operadorea"</string>
     <string name="touch_filtered_warning" msgid="8671693809204767551">"Aplikazio bat baimen-eskaera oztopatzen ari denez, ezarpenek ezin dute egiaztatu erantzuna."</string>
-    <string name="slice_permission_title" msgid="7465009437851044444">"<xliff:g id="APP_0">%1$s</xliff:g> aplikazioari <xliff:g id="APP_2">%2$s</xliff:g> aplikazioaren zatiak erakusteko baimena eman nahi diozu?"</string>
+    <string name="slice_permission_title" msgid="7465009437851044444">"<xliff:g id="APP_2">%2$s</xliff:g> aplikazioaren zatiak erakusteko baimena eman nahi diozu <xliff:g id="APP_0">%1$s</xliff:g> aplikazioari?"</string>
     <string name="slice_permission_text_1" msgid="3514586565609596523">"- <xliff:g id="APP">%1$s</xliff:g> aplikazioaren informazioa irakur dezake."</string>
     <string name="slice_permission_text_2" msgid="3146758297471143723">"- <xliff:g id="APP">%1$s</xliff:g> aplikazioan ekintzak gauza ditzake."</string>
     <string name="slice_permission_checkbox" msgid="7986504458640562900">"Baimendu <xliff:g id="APP">%1$s</xliff:g> aplikazioari edozein aplikazioren zatiak erakustea"</string>
diff --git a/packages/SystemUI/res/values-fa/strings.xml b/packages/SystemUI/res/values-fa/strings.xml
index e649d80..232f7a2 100644
--- a/packages/SystemUI/res/values-fa/strings.xml
+++ b/packages/SystemUI/res/values-fa/strings.xml
@@ -47,6 +47,8 @@
     <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_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_accessory_confirm_prompt" msgid="4333670517539993561">"برای استفاده از <xliff:g id="USB_ACCESSORY">%2$s</xliff:g>، <xliff:g id="APPLICATION">%1$s</xliff:g> باز شود؟"</string>
@@ -126,6 +128,20 @@
     <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="face_dialog_looking_for_face" msgid="7049276266074494689">"درحال جستجوی شما…"</string>
@@ -364,6 +380,8 @@
     </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_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 e195754..5767c3c 100644
--- a/packages/SystemUI/res/values-fi/strings.xml
+++ b/packages/SystemUI/res/values-fi/strings.xml
@@ -47,6 +47,8 @@
     <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_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_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>
@@ -126,6 +128,20 @@
     <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="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>
@@ -364,6 +380,8 @@
     </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_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 4f28efa..04138c0 100644
--- a/packages/SystemUI/res/values-fr-rCA/strings.xml
+++ b/packages/SystemUI/res/values-fr-rCA/strings.xml
@@ -47,6 +47,8 @@
     <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_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_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>
@@ -56,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 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 digitale 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>
@@ -126,6 +128,20 @@
     <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="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>
@@ -364,6 +380,8 @@
     </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_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 a51ebb1..7191426 100644
--- a/packages/SystemUI/res/values-fr/strings.xml
+++ b/packages/SystemUI/res/values-fr/strings.xml
@@ -47,6 +47,8 @@
     <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_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_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>
@@ -126,6 +128,20 @@
     <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="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>
@@ -364,6 +380,8 @@
     </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_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 7a7ebf2..4262d88 100644
--- a/packages/SystemUI/res/values-gl/strings.xml
+++ b/packages/SystemUI/res/values-gl/strings.xml
@@ -47,6 +47,8 @@
     <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_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_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>
@@ -126,6 +128,20 @@
     <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="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>
@@ -364,6 +380,8 @@
     </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_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 10aba24..66f9a7a 100644
--- a/packages/SystemUI/res/values-gu/strings.xml
+++ b/packages/SystemUI/res/values-gu/strings.xml
@@ -47,6 +47,8 @@
     <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_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_accessory_confirm_prompt" msgid="4333670517539993561">"<xliff:g id="USB_ACCESSORY">%2$s</xliff:g>ને હૅન્ડલ કરવા માટે <xliff:g id="APPLICATION">%1$s</xliff:g>ને ખોલીએ?"</string>
@@ -56,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>
@@ -126,6 +128,20 @@
     <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="face_dialog_looking_for_face" msgid="7049276266074494689">"તમારા માટે શોધી રહ્યાં છે..."</string>
@@ -364,6 +380,8 @@
     </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_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 9ce8e7d..c49cae4 100644
--- a/packages/SystemUI/res/values-hi/strings.xml
+++ b/packages/SystemUI/res/values-hi/strings.xml
@@ -47,6 +47,8 @@
     <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_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_accessory_confirm_prompt" msgid="4333670517539993561">"<xliff:g id="USB_ACCESSORY">%2$s</xliff:g> के लिए <xliff:g id="APPLICATION">%1$s</xliff:g> खोलें?"</string>
@@ -126,6 +128,20 @@
     <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="face_dialog_looking_for_face" msgid="7049276266074494689">"आपको पहचान रहा है…"</string>
@@ -364,6 +380,8 @@
     </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_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 9c9b0b0..6086764 100644
--- a/packages/SystemUI/res/values-hr/strings.xml
+++ b/packages/SystemUI/res/values-hr/strings.xml
@@ -47,6 +47,8 @@
     <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_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_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>
@@ -126,6 +128,20 @@
     <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="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>
@@ -366,6 +382,8 @@
     </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_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 99a049e..be039c7 100644
--- a/packages/SystemUI/res/values-hu/strings.xml
+++ b/packages/SystemUI/res/values-hu/strings.xml
@@ -47,6 +47,8 @@
     <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_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_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>
@@ -126,6 +128,20 @@
     <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="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>
@@ -364,6 +380,8 @@
     </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_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 9ac0afb..0f84b50 100644
--- a/packages/SystemUI/res/values-hy/strings.xml
+++ b/packages/SystemUI/res/values-hy/strings.xml
@@ -47,6 +47,8 @@
     <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_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_accessory_confirm_prompt" msgid="4333670517539993561">"Բացե՞լ <xliff:g id="APPLICATION">%1$s</xliff:g> հավելվածը <xliff:g id="USB_ACCESSORY">%2$s</xliff:g> լրասարքը մշակելու համար։"</string>
@@ -126,6 +128,20 @@
     <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="face_dialog_looking_for_face" msgid="7049276266074494689">"Դեմքի ճանաչում…"</string>
@@ -364,6 +380,8 @@
     </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_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 443e3b3..0b3ef70 100644
--- a/packages/SystemUI/res/values-in/strings.xml
+++ b/packages/SystemUI/res/values-in/strings.xml
@@ -47,6 +47,8 @@
     <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_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_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>
@@ -126,6 +128,20 @@
     <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="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>
@@ -364,6 +380,8 @@
     </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_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 f481e48..7a8d290 100644
--- a/packages/SystemUI/res/values-is/strings.xml
+++ b/packages/SystemUI/res/values-is/strings.xml
@@ -47,6 +47,8 @@
     <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_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_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>
@@ -126,6 +128,20 @@
     <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="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>
@@ -364,6 +380,8 @@
     </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_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 718608a..cc053be 100644
--- a/packages/SystemUI/res/values-it/strings.xml
+++ b/packages/SystemUI/res/values-it/strings.xml
@@ -47,6 +47,8 @@
     <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_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_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>
@@ -56,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">"Fingerprint della chiave RSA del computer: \n<xliff:g id="FINGERPRINT">%1$s</xliff:g>"</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_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>
@@ -108,8 +110,8 @@
     <string name="accessibility_phone_button" msgid="6738112589538563574">"Telefono"</string>
     <string name="accessibility_voice_assist_button" msgid="487611083884852965">"Voice Assist"</string>
     <string name="accessibility_unlock_button" msgid="128158454631118828">"Sblocca"</string>
-    <string name="accessibility_waiting_for_fingerprint" msgid="4808860050517462885">"In attesa dell\'impronta digitale"</string>
-    <string name="accessibility_unlock_without_fingerprint" msgid="7541705575183694446">"Sblocca senza utilizzare l\'impronta digitale"</string>
+    <string name="accessibility_waiting_for_fingerprint" msgid="4808860050517462885">"In attesa dell\'impronta"</string>
+    <string name="accessibility_unlock_without_fingerprint" msgid="7541705575183694446">"Sblocca senza utilizzare l\'impronta"</string>
     <string name="accessibility_scanning_face" msgid="769545173211758586">"Scansione del viso"</string>
     <string name="accessibility_send_smart_reply" msgid="7766727839703044493">"Invia"</string>
     <string name="accessibility_manage_notification" msgid="2026361503393549753">"Gestisci notifiche"</string>
@@ -126,8 +128,22 @@
     <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>
-    <string name="fingerprint_dialog_touch_sensor" msgid="8511557690663181761">"Tocca il sensore di impronte digitali"</string>
-    <string name="accessibility_fingerprint_dialog_fingerprint_icon" msgid="3125122495414253226">"Icona dell\'impronta digitale"</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">"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>
     <string name="accessibility_face_dialog_face_icon" msgid="2658119009870383490">"Icona volto"</string>
     <string name="accessibility_compatibility_zoom_button" msgid="8461115318742350699">"Pulsante zoom compatibilità."</string>
@@ -364,6 +380,8 @@
     </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_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 606a097..09e4f0e 100644
--- a/packages/SystemUI/res/values-iw/strings.xml
+++ b/packages/SystemUI/res/values-iw/strings.xml
@@ -47,6 +47,8 @@
     <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_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_accessory_confirm_prompt" msgid="4333670517539993561">"האם לפתוח את <xliff:g id="APPLICATION">%1$s</xliff:g> כדי לעבוד עם <xliff:g id="USB_ACCESSORY">%2$s</xliff:g>?"</string>
@@ -126,6 +128,20 @@
     <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="face_dialog_looking_for_face" msgid="7049276266074494689">"מחפש אותך…"</string>
@@ -368,6 +384,8 @@
     </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_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 0bc500c..3dc9fb7 100644
--- a/packages/SystemUI/res/values-ja/strings.xml
+++ b/packages/SystemUI/res/values-ja/strings.xml
@@ -47,6 +47,8 @@
     <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_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_accessory_confirm_prompt" msgid="4333670517539993561">"<xliff:g id="APPLICATION">%1$s</xliff:g> を起動して <xliff:g id="USB_ACCESSORY">%2$s</xliff:g> を処理しますか?"</string>
@@ -126,6 +128,20 @@
     <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="face_dialog_looking_for_face" msgid="7049276266074494689">"顔を認証しています…"</string>
@@ -364,6 +380,8 @@
     </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_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 b3c7de7..24db256 100644
--- a/packages/SystemUI/res/values-ka/strings.xml
+++ b/packages/SystemUI/res/values-ka/strings.xml
@@ -47,6 +47,8 @@
     <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_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_accessory_confirm_prompt" msgid="4333670517539993561">"გსურთ, გახსნათ <xliff:g id="APPLICATION">%1$s</xliff:g>, <xliff:g id="USB_ACCESSORY">%2$s</xliff:g>-ის გამოსაყენებლად?"</string>
@@ -126,6 +128,20 @@
     <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="face_dialog_looking_for_face" msgid="7049276266074494689">"მიმდინარეობს თქვენი ძიება…"</string>
@@ -364,6 +380,8 @@
     </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_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 e1fa4b2b..ff1b9fc 100644
--- a/packages/SystemUI/res/values-kk/strings.xml
+++ b/packages/SystemUI/res/values-kk/strings.xml
@@ -47,6 +47,8 @@
     <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_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_accessory_confirm_prompt" msgid="4333670517539993561">"<xliff:g id="USB_ACCESSORY">%2$s</xliff:g> жабдығын басқару үшін <xliff:g id="APPLICATION">%1$s</xliff:g> ашылсын ба?"</string>
@@ -126,6 +128,20 @@
     <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="face_dialog_looking_for_face" msgid="7049276266074494689">"Бет ізделуде…"</string>
@@ -364,6 +380,8 @@
     </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_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-km/strings.xml b/packages/SystemUI/res/values-km/strings.xml
index db93aa9..323138c 100644
--- a/packages/SystemUI/res/values-km/strings.xml
+++ b/packages/SystemUI/res/values-km/strings.xml
@@ -47,6 +47,8 @@
     <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_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_accessory_confirm_prompt" msgid="4333670517539993561">"បើក <xliff:g id="APPLICATION">%1$s</xliff:g> ដើម្បីគ្រប់គ្រង <xliff:g id="USB_ACCESSORY">%2$s</xliff:g> មែនទេ?"</string>
@@ -126,6 +128,20 @@
     <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="face_dialog_looking_for_face" msgid="7049276266074494689">"កំពុងស្វែងរកអ្នក…"</string>
@@ -364,6 +380,8 @@
     </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_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 98589ad..ac593e8 100644
--- a/packages/SystemUI/res/values-kn/strings.xml
+++ b/packages/SystemUI/res/values-kn/strings.xml
@@ -47,6 +47,8 @@
     <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_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_accessory_confirm_prompt" msgid="4333670517539993561">"<xliff:g id="USB_ACCESSORY">%2$s</xliff:g> ಅನ್ನು ನಿರ್ವಹಿಸಲು <xliff:g id="APPLICATION">%1$s</xliff:g> ಅನ್ನು ತೆರೆಯುವುದೇ?"</string>
@@ -126,6 +128,20 @@
     <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="face_dialog_looking_for_face" msgid="7049276266074494689">"ನಿಮಗಾಗಿ ಹುಡುಕಲಾಗುತ್ತಿದೆ…"</string>
@@ -364,6 +380,8 @@
     </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_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 03c277e..f37ec00 100644
--- a/packages/SystemUI/res/values-ko/strings.xml
+++ b/packages/SystemUI/res/values-ko/strings.xml
@@ -47,6 +47,8 @@
     <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_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_accessory_confirm_prompt" msgid="4333670517539993561">"<xliff:g id="APPLICATION">%1$s</xliff:g> 앱을 열어 <xliff:g id="USB_ACCESSORY">%2$s</xliff:g>을(를) 처리하시겠습니까?"</string>
@@ -126,6 +128,20 @@
     <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="face_dialog_looking_for_face" msgid="7049276266074494689">"찾는 중..."</string>
@@ -364,6 +380,8 @@
     </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_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 c82e5b0..beb2b02 100644
--- a/packages/SystemUI/res/values-ky/strings.xml
+++ b/packages/SystemUI/res/values-ky/strings.xml
@@ -47,6 +47,8 @@
     <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_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_accessory_confirm_prompt" msgid="4333670517539993561">"<xliff:g id="USB_ACCESSORY">%2$s</xliff:g> кабелине туташуу үчүн <xliff:g id="APPLICATION">%1$s</xliff:g> колдонмосу ачылсынбы?"</string>
@@ -126,6 +128,20 @@
     <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="face_dialog_looking_for_face" msgid="7049276266074494689">"Жүзүңүз изделүүдө…"</string>
@@ -364,6 +380,8 @@
     </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_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>
@@ -902,7 +920,7 @@
     <string name="slice_permission_text_2" msgid="3146758297471143723">"- <xliff:g id="APP">%1$s</xliff:g> колдонмосунда аракеттерди аткарат"</string>
     <string name="slice_permission_checkbox" msgid="7986504458640562900">"<xliff:g id="APP">%1$s</xliff:g> бардык колдонмолордун үлгүлөрүн көрсөтүүгө уруксат берүү"</string>
     <string name="slice_permission_allow" msgid="2340244901366722709">"Уруксат берүү"</string>
-    <string name="slice_permission_deny" msgid="7683681514008048807">"Жок"</string>
+    <string name="slice_permission_deny" msgid="7683681514008048807">"Тыюу салынат"</string>
     <string name="auto_saver_title" msgid="1217959994732964228">"Батареяны үнөмдөгүчтүн тартибин жөндөө үчүн басыңыз"</string>
     <string name="auto_saver_text" msgid="2563289953551438248">"Батареянын кубаты түгөнүп калганда, күйгүзүлсүн"</string>
     <string name="no_auto_saver_action" msgid="8086002101711328500">"Жок, рахмат"</string>
@@ -926,7 +944,7 @@
     <string name="bubbles_settings_button_description" msgid="2970630476657287189">"<xliff:g id="APP_NAME">%1$s</xliff:g> көбүктөрүнүн жөндөөлөрү"</string>
     <string name="bubbles_prompt" msgid="8807968030159469710">"<xliff:g id="APP_NAME">%1$s</xliff:g> колдонмосунун калкып чыкма билдирмелерине уруксат бересизби?"</string>
     <string name="manage_bubbles_text" msgid="7027739766859191408">"Башкаруу"</string>
-    <string name="no_bubbles" msgid="337101288173078247">"Жок"</string>
+    <string name="no_bubbles" msgid="337101288173078247">"Тыюу салынат"</string>
     <string name="yes_bubbles" msgid="668809525728633841">"Уруксат берүү"</string>
     <string name="ask_me_later_bubbles" msgid="2147688438402939029">"Кийинчерээк суралсын"</string>
     <string name="bubble_content_description_single" msgid="1184462974339387516">"<xliff:g id="APP_NAME">%2$s</xliff:g> колдонмосунан <xliff:g id="NOTIFICATION_TITLE">%1$s</xliff:g>"</string>
diff --git a/packages/SystemUI/res/values-lo/strings.xml b/packages/SystemUI/res/values-lo/strings.xml
index 4f4d291..68c9951 100644
--- a/packages/SystemUI/res/values-lo/strings.xml
+++ b/packages/SystemUI/res/values-lo/strings.xml
@@ -47,6 +47,8 @@
     <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_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_accessory_confirm_prompt" msgid="4333670517539993561">"ເປີດ <xliff:g id="APPLICATION">%1$s</xliff:g> ເພື່ອໃຊ້ກັບ <xliff:g id="USB_ACCESSORY">%2$s</xliff:g> ບໍ?"</string>
@@ -126,6 +128,20 @@
     <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="face_dialog_looking_for_face" msgid="7049276266074494689">"ກຳລັງຊອກຫາທ່ານ…"</string>
@@ -364,6 +380,8 @@
     </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_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 ca7c89e..230194d 100644
--- a/packages/SystemUI/res/values-lt/strings.xml
+++ b/packages/SystemUI/res/values-lt/strings.xml
@@ -47,6 +47,8 @@
     <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_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_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>
@@ -126,6 +128,20 @@
     <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="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>
@@ -368,6 +384,8 @@
     </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_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>
@@ -466,7 +484,7 @@
     <string name="media_projection_remember_text" msgid="3103510882172746752">"Daugiau neberodyti"</string>
     <string name="clear_all_notifications_text" msgid="814192889771462828">"Viską išvalyti"</string>
     <string name="manage_notifications_text" msgid="2386728145475108753">"Tvarkyti"</string>
-    <string name="notification_section_header_gentle" msgid="4372438504154095677">"Tylūs pranešimai"</string>
+    <string name="notification_section_header_gentle" msgid="4372438504154095677">"Tylieji pranešimai"</string>
     <string name="accessibility_notification_section_header_gentle_clear_all" msgid="4286716295850400959">"Išvalyti visus tylius pranešimus"</string>
     <string name="dnd_suppressing_shade_text" msgid="1904574852846769301">"Pranešimai pristabdyti naudojant netrukdymo režimą"</string>
     <string name="media_projection_action_text" msgid="8470872969457985954">"Pradėti dabar"</string>
diff --git a/packages/SystemUI/res/values-lv/strings.xml b/packages/SystemUI/res/values-lv/strings.xml
index 424e104..e1905f5 100644
--- a/packages/SystemUI/res/values-lv/strings.xml
+++ b/packages/SystemUI/res/values-lv/strings.xml
@@ -47,6 +47,8 @@
     <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_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_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>
@@ -126,6 +128,20 @@
     <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="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>
@@ -366,6 +382,8 @@
     </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_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 dd86ede..300dff5 100644
--- a/packages/SystemUI/res/values-mk/strings.xml
+++ b/packages/SystemUI/res/values-mk/strings.xml
@@ -47,6 +47,8 @@
     <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_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_accessory_confirm_prompt" msgid="4333670517539993561">"Да се отвори <xliff:g id="APPLICATION">%1$s</xliff:g> за да управува со <xliff:g id="USB_ACCESSORY">%2$s</xliff:g>?"</string>
@@ -126,6 +128,20 @@
     <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="face_dialog_looking_for_face" msgid="7049276266074494689">"Ве бараме вас…"</string>
@@ -364,6 +380,8 @@
     </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_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 859e65b..0a06b2c 100644
--- a/packages/SystemUI/res/values-ml/strings.xml
+++ b/packages/SystemUI/res/values-ml/strings.xml
@@ -47,6 +47,8 @@
     <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_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_accessory_confirm_prompt" msgid="4333670517539993561">"<xliff:g id="USB_ACCESSORY">%2$s</xliff:g> കൈകാര്യം ചെയ്യാൻ <xliff:g id="APPLICATION">%1$s</xliff:g> തുറക്കണോ?"</string>
@@ -126,6 +128,20 @@
     <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="face_dialog_looking_for_face" msgid="7049276266074494689">"നിങ്ങൾക്കായി തിരയുന്നു…"</string>
@@ -364,6 +380,8 @@
     </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_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>
@@ -377,7 +395,7 @@
     <string name="quick_settings_night_secondary_label_until_sunrise" msgid="4453017157391574402">"സൂര്യോദയം വരെ"</string>
     <string name="quick_settings_night_secondary_label_on_at" msgid="6256314040368487637">"<xliff:g id="TIME">%s</xliff:g>-ന്"</string>
     <string name="quick_settings_secondary_label_until" msgid="2749196569462600150">"<xliff:g id="TIME">%s</xliff:g> വരെ"</string>
-    <string name="quick_settings_ui_mode_night_label" msgid="3419947801072692538">"ഇരുണ്ട തീം"</string>
+    <string name="quick_settings_ui_mode_night_label" msgid="3419947801072692538">"ഡാർക്ക് തീം"</string>
     <string name="quick_settings_ui_mode_night_label_battery_saver" msgid="7438725724589758362">"ഇരുണ്ട തീം\nബാറ്ററി ലാഭിക്കൽ"</string>
     <string name="quick_settings_nfc_label" msgid="9012153754816969325">"NFC"</string>
     <string name="quick_settings_nfc_off" msgid="6883274004315134333">"NFC പ്രവർത്തനരഹിതമാക്കി"</string>
diff --git a/packages/SystemUI/res/values-mn/strings.xml b/packages/SystemUI/res/values-mn/strings.xml
index 3363af7..0298d20 100644
--- a/packages/SystemUI/res/values-mn/strings.xml
+++ b/packages/SystemUI/res/values-mn/strings.xml
@@ -47,6 +47,8 @@
     <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_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_accessory_confirm_prompt" msgid="4333670517539993561">"<xliff:g id="USB_ACCESSORY">%2$s</xliff:g>-г зохицуулахын тулд <xliff:g id="APPLICATION">%1$s</xliff:g>-г нээх үү?"</string>
@@ -126,6 +128,20 @@
     <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="face_dialog_looking_for_face" msgid="7049276266074494689">"Таныг хайж байна…"</string>
@@ -364,6 +380,8 @@
     </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_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 f785fe9..07b985f 100644
--- a/packages/SystemUI/res/values-mr/strings.xml
+++ b/packages/SystemUI/res/values-mr/strings.xml
@@ -47,6 +47,8 @@
     <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_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_accessory_confirm_prompt" msgid="4333670517539993561">"<xliff:g id="USB_ACCESSORY">%2$s</xliff:g> हाताळण्यासाठी <xliff:g id="APPLICATION">%1$s</xliff:g> उघडायचे का?"</string>
@@ -126,6 +128,20 @@
     <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="face_dialog_looking_for_face" msgid="7049276266074494689">"तुमच्यासाठी शोधत आहे…"</string>
@@ -364,6 +380,8 @@
     </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_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 352c376..f696ee3 100644
--- a/packages/SystemUI/res/values-ms/strings.xml
+++ b/packages/SystemUI/res/values-ms/strings.xml
@@ -47,6 +47,8 @@
     <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_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_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>
@@ -126,6 +128,20 @@
     <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="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>
@@ -364,6 +380,8 @@
     </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_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 d136042..eb73df7 100644
--- a/packages/SystemUI/res/values-my/strings.xml
+++ b/packages/SystemUI/res/values-my/strings.xml
@@ -47,6 +47,8 @@
     <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_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_accessory_confirm_prompt" msgid="4333670517539993561">"<xliff:g id="USB_ACCESSORY">%2$s</xliff:g> ဆောင်ရွက်ရန် <xliff:g id="APPLICATION">%1$s</xliff:g> ကို ဖွင့်လိုပါသလား။"</string>
@@ -126,6 +128,20 @@
     <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="face_dialog_looking_for_face" msgid="7049276266074494689">"သင့်ကို ရှာဖွေနေသည်…"</string>
@@ -364,6 +380,8 @@
     </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_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 86f0b38..9e1c5db 100644
--- a/packages/SystemUI/res/values-nb/strings.xml
+++ b/packages/SystemUI/res/values-nb/strings.xml
@@ -47,6 +47,8 @@
     <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_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_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>
@@ -126,6 +128,20 @@
     <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="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>
@@ -364,6 +380,8 @@
     </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_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 4c17904..5a00002 100644
--- a/packages/SystemUI/res/values-ne/strings.xml
+++ b/packages/SystemUI/res/values-ne/strings.xml
@@ -47,6 +47,8 @@
     <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_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_accessory_confirm_prompt" msgid="4333670517539993561">"<xliff:g id="USB_ACCESSORY">%2$s</xliff:g> को व्यवस्थापन गर्न <xliff:g id="APPLICATION">%1$s</xliff:g> खोल्ने हो?"</string>
@@ -126,6 +128,20 @@
     <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="face_dialog_looking_for_face" msgid="7049276266074494689">"तपाईंलाई खोज्दै…"</string>
@@ -364,6 +380,8 @@
     </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_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 c62c579..dacbd53 100644
--- a/packages/SystemUI/res/values-nl/strings.xml
+++ b/packages/SystemUI/res/values-nl/strings.xml
@@ -47,6 +47,8 @@
     <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_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_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>
@@ -126,6 +128,20 @@
     <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="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>
@@ -364,6 +380,8 @@
     </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_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 d295925..2720abf 100644
--- a/packages/SystemUI/res/values-or/strings.xml
+++ b/packages/SystemUI/res/values-or/strings.xml
@@ -47,6 +47,8 @@
     <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_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_accessory_confirm_prompt" msgid="4333670517539993561">"<xliff:g id="USB_ACCESSORY">%2$s</xliff:g> ନିୟନ୍ତ୍ରଣ କରିବାକୁ <xliff:g id="APPLICATION">%1$s</xliff:g> ଖୋଲିବେ?"</string>
@@ -126,6 +128,20 @@
     <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="face_dialog_looking_for_face" msgid="7049276266074494689">"ଆପଣଙ୍କୁ ଚିହ୍ନଟ କରୁଛି…"</string>
@@ -364,6 +380,8 @@
     </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_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 b75deb9..805a580 100644
--- a/packages/SystemUI/res/values-pa/strings.xml
+++ b/packages/SystemUI/res/values-pa/strings.xml
@@ -47,6 +47,8 @@
     <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_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_accessory_confirm_prompt" msgid="4333670517539993561">"ਕੀ <xliff:g id="USB_ACCESSORY">%2$s</xliff:g> ਨੂੰ ਵਰਤਣ ਲਈ <xliff:g id="APPLICATION">%1$s</xliff:g> ਖੋਲ੍ਹਣੀ ਹੈ?"</string>
@@ -126,6 +128,20 @@
     <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="face_dialog_looking_for_face" msgid="7049276266074494689">"ਤੁਹਾਡੀ ਪਛਾਣ ਕੀਤੀ ਜਾ ਰਹੀ ਹੈ…"</string>
@@ -364,6 +380,8 @@
     </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_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 d372b3d..16dfff3 100644
--- a/packages/SystemUI/res/values-pl/strings.xml
+++ b/packages/SystemUI/res/values-pl/strings.xml
@@ -47,6 +47,8 @@
     <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_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_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>
@@ -126,6 +128,20 @@
     <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="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>
@@ -370,6 +386,8 @@
     </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_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 2b76157..25ca226 100644
--- a/packages/SystemUI/res/values-pt-rBR/strings.xml
+++ b/packages/SystemUI/res/values-pt-rBR/strings.xml
@@ -47,6 +47,8 @@
     <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_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_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>
@@ -126,6 +128,20 @@
     <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="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>
@@ -364,6 +380,8 @@
     </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_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 17cc86f..fdb98fa 100644
--- a/packages/SystemUI/res/values-pt-rPT/strings.xml
+++ b/packages/SystemUI/res/values-pt-rPT/strings.xml
@@ -47,6 +47,8 @@
     <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_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_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>
@@ -68,7 +70,7 @@
     <string name="learn_more" msgid="5000517160980853569">"Saiba mais"</string>
     <string name="compat_mode_on" msgid="6623839244840638213">"Zoom para preencher o ecrã"</string>
     <string name="compat_mode_off" msgid="4434467572461327898">"Esticar p. caber em ec. int."</string>
-    <string name="global_action_screenshot" msgid="8329831278085426283">"Captura de ecrã"</string>
+    <string name="global_action_screenshot" msgid="8329831278085426283">"Capt. ecrã"</string>
     <string name="screenshot_saving_ticker" msgid="7403652894056693515">"A guardar captura de ecrã..."</string>
     <string name="screenshot_saving_title" msgid="8242282144535555697">"A guardar captura de ecrã..."</string>
     <string name="screenshot_saved_title" msgid="5637073968117370753">"Captura de ecrã guardada"</string>
@@ -126,6 +128,20 @@
     <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="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>
@@ -364,6 +380,8 @@
     </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_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 2b76157..25ca226 100644
--- a/packages/SystemUI/res/values-pt/strings.xml
+++ b/packages/SystemUI/res/values-pt/strings.xml
@@ -47,6 +47,8 @@
     <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_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_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>
@@ -126,6 +128,20 @@
     <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="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>
@@ -364,6 +380,8 @@
     </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_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 db8f87d..171ca9a 100644
--- a/packages/SystemUI/res/values-ro/strings.xml
+++ b/packages/SystemUI/res/values-ro/strings.xml
@@ -47,6 +47,8 @@
     <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_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_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>
@@ -56,7 +58,7 @@
     <string name="always_use_device" msgid="4015357883336738417">"Deschideți întotdeauna <xliff:g id="APPLICATION">%1$s</xliff:g> când este conectat <xliff:g id="USB_DEVICE">%2$s</xliff:g>"</string>
     <string name="always_use_accessory" msgid="3257892669444535154">"Deschideți întotdeauna <xliff:g id="APPLICATION">%1$s</xliff:g> când este conectat <xliff:g id="USB_ACCESSORY">%2$s</xliff:g>"</string>
     <string name="usb_debugging_title" msgid="4513918393387141949">"Permiteți remedierea erorilor prin USB?"</string>
-    <string name="usb_debugging_message" msgid="2220143855912376496">"Amprenta digitală din cheia RSA a computerului este:\n<xliff:g id="FINGERPRINT">%1$s</xliff:g>"</string>
+    <string name="usb_debugging_message" msgid="2220143855912376496">"Amprenta din cheia RSA a computerului este:\n<xliff:g id="FINGERPRINT">%1$s</xliff:g>"</string>
     <string name="usb_debugging_always" msgid="303335496705863070">"Permiteți întotdeauna de pe acest computer"</string>
     <string name="usb_debugging_allow" msgid="2272145052073254852">"Permiteți"</string>
     <string name="usb_debugging_secondary_user_title" msgid="6353808721761220421">"Remedierea erorilor prin USB nu este permisă"</string>
@@ -126,6 +128,20 @@
     <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="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>
@@ -366,6 +382,8 @@
     </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_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 f7527d9..1d7f6c8 100644
--- a/packages/SystemUI/res/values-ru/strings.xml
+++ b/packages/SystemUI/res/values-ru/strings.xml
@@ -47,6 +47,8 @@
     <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_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_accessory_confirm_prompt" msgid="4333670517539993561">"Открыть приложение \"<xliff:g id="APPLICATION">%1$s</xliff:g>\" для управления устройством \"<xliff:g id="USB_ACCESSORY">%2$s</xliff:g>\"?"</string>
@@ -126,6 +128,20 @@
     <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="face_dialog_looking_for_face" msgid="7049276266074494689">"Поиск лица…"</string>
@@ -368,6 +384,8 @@
     </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_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 c87ef5a..fa1c109 100644
--- a/packages/SystemUI/res/values-si/strings.xml
+++ b/packages/SystemUI/res/values-si/strings.xml
@@ -47,6 +47,8 @@
     <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_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_accessory_confirm_prompt" msgid="4333670517539993561">"<xliff:g id="USB_ACCESSORY">%2$s</xliff:g> හැසිරවීමට <xliff:g id="APPLICATION">%1$s</xliff:g> විවෘත කරන්නද?"</string>
@@ -126,6 +128,20 @@
     <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="face_dialog_looking_for_face" msgid="7049276266074494689">"ඔබව සොයමින්…"</string>
@@ -364,6 +380,8 @@
     </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_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 1e171a1..ddb0ed4 100644
--- a/packages/SystemUI/res/values-sk/strings.xml
+++ b/packages/SystemUI/res/values-sk/strings.xml
@@ -47,6 +47,8 @@
     <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_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_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>
@@ -126,6 +128,20 @@
     <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="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>
@@ -368,6 +384,8 @@
     </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_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 b342ce6..1af84fe 100644
--- a/packages/SystemUI/res/values-sl/strings.xml
+++ b/packages/SystemUI/res/values-sl/strings.xml
@@ -47,6 +47,8 @@
     <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_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_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>
@@ -126,6 +128,20 @@
     <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="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>
@@ -368,6 +384,8 @@
     </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_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 4fba770..344aae3 100644
--- a/packages/SystemUI/res/values-sq/strings.xml
+++ b/packages/SystemUI/res/values-sq/strings.xml
@@ -47,6 +47,8 @@
     <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_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_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>
@@ -56,7 +58,7 @@
     <string name="always_use_device" msgid="4015357883336738417">"Hap gjithmonë <xliff:g id="APPLICATION">%1$s</xliff:g> kur lidhet <xliff:g id="USB_DEVICE">%2$s</xliff:g>"</string>
     <string name="always_use_accessory" msgid="3257892669444535154">"Hap gjithmonë <xliff:g id="APPLICATION">%1$s</xliff:g> kur lidhet <xliff:g id="USB_ACCESSORY">%2$s</xliff:g>"</string>
     <string name="usb_debugging_title" msgid="4513918393387141949">"Të lejohet korrigjimi i USB-së?"</string>
-    <string name="usb_debugging_message" msgid="2220143855912376496">"Shenja e gishtit të tastit \"RSA\" së kompjuterit është:\n<xliff:g id="FINGERPRINT">%1$s</xliff:g>"</string>
+    <string name="usb_debugging_message" msgid="2220143855912376496">"Gjurma e gishtit të tastit \"RSA\" së kompjuterit është:\n<xliff:g id="FINGERPRINT">%1$s</xliff:g>"</string>
     <string name="usb_debugging_always" msgid="303335496705863070">"Lejo gjithmonë nga ky kompjuter"</string>
     <string name="usb_debugging_allow" msgid="2272145052073254852">"Lejo"</string>
     <string name="usb_debugging_secondary_user_title" msgid="6353808721761220421">"Korrigjimi i USB-së nuk lejohet"</string>
@@ -126,6 +128,20 @@
     <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="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>
@@ -364,6 +380,8 @@
     </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_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 310fc6f..b36b9dc 100644
--- a/packages/SystemUI/res/values-sr/strings.xml
+++ b/packages/SystemUI/res/values-sr/strings.xml
@@ -47,6 +47,8 @@
     <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_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_accessory_confirm_prompt" msgid="4333670517539993561">"Желите ли да отворите апликацију <xliff:g id="APPLICATION">%1$s</xliff:g> да бисте користили уређај <xliff:g id="USB_ACCESSORY">%2$s</xliff:g>?"</string>
@@ -126,6 +128,20 @@
     <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="face_dialog_looking_for_face" msgid="7049276266074494689">"Тражимо вас…"</string>
@@ -366,6 +382,8 @@
     </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_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 54769cd..24e0b1e 100644
--- a/packages/SystemUI/res/values-sv/strings.xml
+++ b/packages/SystemUI/res/values-sv/strings.xml
@@ -47,6 +47,8 @@
     <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_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_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>
@@ -126,6 +128,20 @@
     <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="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>
@@ -364,6 +380,8 @@
     </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_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 3f9278a..93f5b7d 100644
--- a/packages/SystemUI/res/values-sw/strings.xml
+++ b/packages/SystemUI/res/values-sw/strings.xml
@@ -47,6 +47,8 @@
     <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_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_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>
@@ -126,6 +128,20 @@
     <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="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>
@@ -364,6 +380,8 @@
     </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_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 0f36889..a5aa91d 100644
--- a/packages/SystemUI/res/values-ta/strings.xml
+++ b/packages/SystemUI/res/values-ta/strings.xml
@@ -47,6 +47,8 @@
     <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_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_accessory_confirm_prompt" msgid="4333670517539993561">"<xliff:g id="USB_ACCESSORY">%2$s</xliff:g>ஐக் கையாள, <xliff:g id="APPLICATION">%1$s</xliff:g> பயன்பாட்டைத் திறக்கவா?"</string>
@@ -126,6 +128,20 @@
     <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="face_dialog_looking_for_face" msgid="7049276266074494689">"உங்கள் முகத்தைத் தேடுகிறது…"</string>
@@ -364,6 +380,8 @@
     </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_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>
@@ -498,29 +516,29 @@
     <string name="monitoring_description_managed_profile_ca_certificate" msgid="4683248196789897964">"உங்கள் நிறுவனம், பணிக் கணக்கில் சான்றிதழ் அங்கீகாரத்தை நிறுவியுள்ளது. உங்களின் பாதுகாப்பான நெட்வொர்க் ட்ராஃபிக் கண்காணிக்கப்படலாம் அல்லது மாற்றப்படலாம்."</string>
     <string name="monitoring_description_ca_certificate" msgid="7886985418413598352">"இந்தச் சாதனத்தில் சான்றிதழ் அங்கீகாரம் நிறுவப்பட்டுள்ளது. உங்களின் பாதுகாப்பான நெட்வொர்க் ட்ராஃபிக் கண்காணிக்கப்படலாம் அல்லது மாற்றப்படலாம்."</string>
     <string name="monitoring_description_management_network_logging" msgid="7184005419733060736">"உங்கள் நிர்வாகி, நெட்வொர்க் பதிவெடுத்தலை இயக்கியுள்ளார். இது சாதனத்தில் ட்ராஃபிக்கைக் கண்காணிக்கும்."</string>
-    <string name="monitoring_description_named_vpn" msgid="7403457334088909254">"மின்னஞ்சல்கள், பயன்பாடுகள், இணையதளங்கள் உட்பட உங்கள் நெட்வொர்க் செயல்பாட்டைக் கண்காணிக்கக்கூடிய <xliff:g id="VPN_APP">%1$s</xliff:g> உடன் இணைக்கப்பட்டுள்ளீர்கள்."</string>
-    <string name="monitoring_description_two_named_vpns" msgid="4198511413729213802">"மின்னஞ்சல்கள், பயன்பாடுகள், இணையதளங்கள் உட்பட உங்கள் நெட்வொர்க் செயல்பாட்டைக் கண்காணிக்கக்கூடிய <xliff:g id="VPN_APP_0">%1$s</xliff:g> மற்றும் <xliff:g id="VPN_APP_1">%2$s</xliff:g> உடன் இணைக்கப்பட்டுள்ளீர்கள்."</string>
-    <string name="monitoring_description_managed_profile_named_vpn" msgid="1427905889862420559">"மின்னஞ்சல்கள், பயன்பாடுகள், இணையதளங்கள் உட்பட உங்கள் நெட்வொர்க் செயல்பாட்டைக் கண்காணிக்கக்கூடிய <xliff:g id="VPN_APP">%1$s</xliff:g> உடன் உங்கள் பணிக் கணக்கு இணைக்கப்பட்டுள்ளது."</string>
-    <string name="monitoring_description_personal_profile_named_vpn" msgid="3133980926929069283">"மின்னஞ்சல்கள், பயன்பாடுகள், இணையதளங்கள் உட்பட உங்கள் நெட்வொர்க் செயல்பாட்டைக் கண்காணிக்கக்கூடிய <xliff:g id="VPN_APP">%1$s</xliff:g> உடன் உங்களின் தனிப்பட்ட சுயவிவரம் இணைக்கப்பட்டுள்ளது."</string>
+    <string name="monitoring_description_named_vpn" msgid="7403457334088909254">"மின்னஞ்சல்கள், ஆப்ஸ், இணையதளங்கள் உட்பட உங்கள் நெட்வொர்க் செயல்பாட்டைக் கண்காணிக்கக்கூடிய <xliff:g id="VPN_APP">%1$s</xliff:g> உடன் இணைக்கப்பட்டுள்ளீர்கள்."</string>
+    <string name="monitoring_description_two_named_vpns" msgid="4198511413729213802">"மின்னஞ்சல்கள், ஆப்ஸ், இணையதளங்கள் உட்பட உங்கள் நெட்வொர்க் செயல்பாட்டைக் கண்காணிக்கக்கூடிய <xliff:g id="VPN_APP_0">%1$s</xliff:g> மற்றும் <xliff:g id="VPN_APP_1">%2$s</xliff:g> உடன் இணைக்கப்பட்டுள்ளீர்கள்."</string>
+    <string name="monitoring_description_managed_profile_named_vpn" msgid="1427905889862420559">"மின்னஞ்சல்கள், ஆப்ஸ், இணையதளங்கள் உட்பட உங்கள் நெட்வொர்க் செயல்பாட்டைக் கண்காணிக்கக்கூடிய <xliff:g id="VPN_APP">%1$s</xliff:g> உடன் உங்கள் பணிக் கணக்கு இணைக்கப்பட்டுள்ளது."</string>
+    <string name="monitoring_description_personal_profile_named_vpn" msgid="3133980926929069283">"மின்னஞ்சல்கள், ஆப்ஸ், இணையதளங்கள் உட்பட உங்கள் நெட்வொர்க் செயல்பாட்டைக் கண்காணிக்கக்கூடிய <xliff:g id="VPN_APP">%1$s</xliff:g> உடன் உங்களின் தனிப்பட்ட சுயவிவரம் இணைக்கப்பட்டுள்ளது."</string>
     <string name="monitoring_description_do_header_generic" msgid="96588491028288691">"உங்கள் சாதனத்தை நிர்வகிப்பது: <xliff:g id="DEVICE_OWNER_APP">%1$s</xliff:g>."</string>
     <string name="monitoring_description_do_header_with_name" msgid="5511133708978206460">"உங்கள் சாதனத்தை நிர்வகிக்க, <xliff:g id="DEVICE_OWNER_APP">%2$s</xliff:g> ஆப்ஸை <xliff:g id="ORGANIZATION_NAME">%1$s</xliff:g> பயன்படுத்தும்."</string>
     <string name="monitoring_description_do_body" msgid="3639594537660975895">"உங்கள் நிர்வாகியால் அமைப்புகள், நிறுவன அணுகல், ஆப்ஸ், சாதனத்துடன் தொடர்புடைய டேட்டா, சாதன இருப்பிடத் தகவல் ஆகியவற்றைக் கண்காணிக்கவும் நிர்வகிக்கவும் முடியும்."</string>
     <string name="monitoring_description_do_learn_more_separator" msgid="3785251953067436862">" "</string>
     <string name="monitoring_description_do_learn_more" msgid="1849514470437907421">"மேலும் அறிக"</string>
-    <string name="monitoring_description_do_body_vpn" msgid="8255218762488901796">"<xliff:g id="VPN_APP">%1$s</xliff:g> உடன் இணைக்கப்பட்டுள்ளீர்கள். இந்த ஆப்ஸால் மின்னஞ்சல்கள், பயன்பாடுகள், இணையதளங்கள் உட்பட உங்கள் நெட்வொர்க் செயல்பாட்டைக் கண்காணிக்க முடியும்."</string>
+    <string name="monitoring_description_do_body_vpn" msgid="8255218762488901796">"<xliff:g id="VPN_APP">%1$s</xliff:g> உடன் இணைக்கப்பட்டுள்ளீர்கள். இந்த ஆப்ஸால் மின்னஞ்சல்கள், ஆப்ஸ், இணையதளங்கள் உட்பட உங்கள் நெட்வொர்க் செயல்பாட்டைக் கண்காணிக்க முடியும்."</string>
     <string name="monitoring_description_vpn_settings_separator" msgid="1933186756733474388">" "</string>
     <string name="monitoring_description_vpn_settings" msgid="6434859242636063861">"VPN அமைப்புகளைத் திற"</string>
     <string name="monitoring_description_ca_cert_settings_separator" msgid="4987350385906393626">" "</string>
     <string name="monitoring_description_ca_cert_settings" msgid="5489969458872997092">"நம்பகமான அனுமதிச் சான்றுகளைத் திற"</string>
     <string name="monitoring_description_network_logging" msgid="7223505523384076027">"உங்கள் நிர்வாகி நெட்வொர்க் பதிவெடுத்தலை இயக்கியுள்ளார், இது சாதனத்தில் ட்ராஃபிக்கைக் கண்காணிக்கும்.\n\nமேலும் தகவலுக்கு, உங்கள் நிர்வாகியைத் தொடர்புகொள்ளவும்."</string>
-    <string name="monitoring_description_vpn" msgid="4445150119515393526">"VPN இணைப்பை அமைக்க, பயன்பாட்டிற்கு அனுமதி வழங்கியுள்ளீர்கள்.\n\nஇந்த ஆப்ஸால் மின்னஞ்சல்கள், பயன்பாடுகள் மற்றும் இணையதளங்கள் உட்பட, உங்கள் சாதனத்தையும் நெட்வொர்க் செயல்பாட்டையும் கண்காணிக்க முடியும்."</string>
-    <string name="monitoring_description_vpn_profile_owned" msgid="2958019119161161530">"உங்கள் பணிக் கணக்கை <xliff:g id="ORGANIZATION">%1$s</xliff:g> நிர்வகிக்கிறது.\n\nஉங்கள் நிர்வாகியால் பயன்பாடுகள், இணையதளங்கள் உட்பட உங்கள் நெட்வொர்க் செயல்பாட்டைக் கண்காணிக்க முடியும்.\n\nமேலும் தகவலுக்கு, உங்கள் நிர்வாகியைத் தொடர்புகொள்ளவும்.\n\nஉங்கள் நெட்வொர்க் செயல்பாட்டைக் கண்காணிக்கக்கூடிய VPN உடனும் இணைக்கப்பட்டுள்ளீர்கள்."</string>
+    <string name="monitoring_description_vpn" msgid="4445150119515393526">"VPN இணைப்பை அமைக்க, பயன்பாட்டிற்கு அனுமதி வழங்கியுள்ளீர்கள்.\n\nஇந்த ஆப்ஸால் மின்னஞ்சல்கள், ஆப்ஸ் மற்றும் இணையதளங்கள் உட்பட, உங்கள் சாதனத்தையும் நெட்வொர்க் செயல்பாட்டையும் கண்காணிக்க முடியும்."</string>
+    <string name="monitoring_description_vpn_profile_owned" msgid="2958019119161161530">"உங்கள் பணிக் கணக்கை <xliff:g id="ORGANIZATION">%1$s</xliff:g> நிர்வகிக்கிறது.\n\nஉங்கள் நிர்வாகியால் ஆப்ஸ், இணையதளங்கள் உட்பட உங்கள் நெட்வொர்க் செயல்பாட்டைக் கண்காணிக்க முடியும்.\n\nமேலும் தகவலுக்கு, உங்கள் நிர்வாகியைத் தொடர்புகொள்ளவும்.\n\nஉங்கள் நெட்வொர்க் செயல்பாட்டைக் கண்காணிக்கக்கூடிய VPN உடனும் இணைக்கப்பட்டுள்ளீர்கள்."</string>
     <string name="legacy_vpn_name" msgid="6604123105765737830">"VPN"</string>
-    <string name="monitoring_description_app" msgid="1828472472674709532">"மின்னஞ்சல்கள், பயன்பாடுகள், இணையதளங்கள் உட்பட உங்கள் நெட்வொர்க் செயல்பாட்டைக் கண்காணிக்கக்கூடிய <xliff:g id="APPLICATION">%1$s</xliff:g> உடன் இணைக்கப்பட்டுள்ளீர்கள்."</string>
-    <string name="monitoring_description_app_personal" msgid="484599052118316268">"<xliff:g id="APPLICATION">%1$s</xliff:g> உடன் இணைக்கப்பட்டுள்ளீர்கள். இந்த ஆப்ஸால், மின்னஞ்சல்கள், பயன்பாடுகள் மற்றும் இணையதளங்கள் உட்பட உங்கள் தனிப்பட்ட நெட்வொர்க் செயல்பாட்டைக் கண்காணிக்க முடியும்."</string>
-    <string name="branded_monitoring_description_app_personal" msgid="2669518213949202599">"<xliff:g id="APPLICATION">%1$s</xliff:g> உடன் இணைக்கப்பட்டுள்ளீர்கள். இந்த ஆப்ஸால் மின்னஞ்சல்கள், பயன்பாடுகள், இணையதளங்கள் உட்பட உங்கள் தனிப்பட்ட நெட்வொர்க் செயல்பாட்டைக் கண்காணிக்க முடியும்."</string>
-    <string name="monitoring_description_app_work" msgid="4612997849787922906">"உங்கள் பணிக் கணக்கை <xliff:g id="ORGANIZATION">%1$s</xliff:g> நிர்வகிக்கிறது. மின்னஞ்சல்கள், பயன்பாடுகள், இணையதளங்கள் உட்பட உங்கள் பணி நெட்வொர்க் செயல்பாட்டைக் கண்காணிக்கக்கூடிய <xliff:g id="APPLICATION">%2$s</xliff:g> உடன் அது இணைக்கப்பட்டுள்ளது.\n\nமேலும் தகவலுக்கு, நிர்வாகியைத் தொடர்புகொள்ளவும்."</string>
-    <string name="monitoring_description_app_personal_work" msgid="5664165460056859391">"உங்கள் பணிக் கணக்கை <xliff:g id="ORGANIZATION">%1$s</xliff:g> நிர்வகிக்கிறது. மின்னஞ்சல்கள், பயன்பாடுகள், இணையதளங்கள் உட்பட உங்கள் பணி நெட்வொர்க் செயல்பாட்டைக் கண்காணிக்கக்கூடிய <xliff:g id="APPLICATION_WORK">%2$s</xliff:g> உடன் அது இணைக்கப்பட்டுள்ளது.\n\nஉங்கள் தனிப்பட்ட நெட்வொர்க் செயல்பாட்டைக் கண்காணிக்கக்கூடிய <xliff:g id="APPLICATION_PERSONAL">%3$s</xliff:g> உடனும் இணைக்கப்பட்டுள்ளீர்கள்."</string>
+    <string name="monitoring_description_app" msgid="1828472472674709532">"மின்னஞ்சல்கள், ஆப்ஸ், இணையதளங்கள் உட்பட உங்கள் நெட்வொர்க் செயல்பாட்டைக் கண்காணிக்கக்கூடிய <xliff:g id="APPLICATION">%1$s</xliff:g> உடன் இணைக்கப்பட்டுள்ளீர்கள்."</string>
+    <string name="monitoring_description_app_personal" msgid="484599052118316268">"<xliff:g id="APPLICATION">%1$s</xliff:g> உடன் இணைக்கப்பட்டுள்ளீர்கள். இந்த ஆப்ஸால், மின்னஞ்சல்கள், ஆப்ஸ் மற்றும் இணையதளங்கள் உட்பட உங்கள் தனிப்பட்ட நெட்வொர்க் செயல்பாட்டைக் கண்காணிக்க முடியும்."</string>
+    <string name="branded_monitoring_description_app_personal" msgid="2669518213949202599">"<xliff:g id="APPLICATION">%1$s</xliff:g> உடன் இணைக்கப்பட்டுள்ளீர்கள். இந்த ஆப்ஸால் மின்னஞ்சல்கள், ஆப்ஸ், இணையதளங்கள் உட்பட உங்கள் தனிப்பட்ட நெட்வொர்க் செயல்பாட்டைக் கண்காணிக்க முடியும்."</string>
+    <string name="monitoring_description_app_work" msgid="4612997849787922906">"உங்கள் பணிக் கணக்கை <xliff:g id="ORGANIZATION">%1$s</xliff:g> நிர்வகிக்கிறது. மின்னஞ்சல்கள், ஆப்ஸ், இணையதளங்கள் உட்பட உங்கள் பணி நெட்வொர்க் செயல்பாட்டைக் கண்காணிக்கக்கூடிய <xliff:g id="APPLICATION">%2$s</xliff:g> உடன் அது இணைக்கப்பட்டுள்ளது.\n\nமேலும் தகவலுக்கு, நிர்வாகியைத் தொடர்புகொள்ளவும்."</string>
+    <string name="monitoring_description_app_personal_work" msgid="5664165460056859391">"உங்கள் பணிக் கணக்கை <xliff:g id="ORGANIZATION">%1$s</xliff:g> நிர்வகிக்கிறது. மின்னஞ்சல்கள், ஆப்ஸ், இணையதளங்கள் உட்பட உங்கள் பணி நெட்வொர்க் செயல்பாட்டைக் கண்காணிக்கக்கூடிய <xliff:g id="APPLICATION_WORK">%2$s</xliff:g> உடன் அது இணைக்கப்பட்டுள்ளது.\n\nஉங்கள் தனிப்பட்ட நெட்வொர்க் செயல்பாட்டைக் கண்காணிக்கக்கூடிய <xliff:g id="APPLICATION_PERSONAL">%3$s</xliff:g> உடனும் இணைக்கப்பட்டுள்ளீர்கள்."</string>
     <string name="keyguard_indication_trust_unlocked" msgid="2712865815371519117">"TrustAgent இதைத் திறந்தே வைத்துள்ளது"</string>
     <string name="keyguard_indication_trust_disabled" msgid="7412534203633528135">"நீங்கள் கைமுறையாகத் திறக்கும் வரை, சாதனம் பூட்டப்பட்டிருக்கும்"</string>
     <string name="hidden_notifications_title" msgid="7139628534207443290">"விரைவாக அறிவிப்புகளைப் பெறுதல்"</string>
@@ -846,7 +864,7 @@
     <string name="pip_skip_to_prev" msgid="1955311326688637914">"முந்தையதற்குச் செல்"</string>
     <string name="thermal_shutdown_title" msgid="4458304833443861111">"வெப்பத்தினால் ஃபோன் ஆஃப் செய்யப்பட்டது"</string>
     <string name="thermal_shutdown_message" msgid="9006456746902370523">"இப்போது உங்கள் ஃபோன் இயல்புநிலையில் இயங்குகிறது"</string>
-    <string name="thermal_shutdown_dialog_message" msgid="566347880005304139">"உங்கள் ஃபோன் அதிகமாகச் சூடானதால், அதன் சூட்டைக் குறைக்க, ஆஃப் செய்யப்பட்டது. இப்போது உங்கள் ஃபோன் இயல்புநிலையில் இயங்குகிறது.\n\nபின்வருவனவற்றைச் செய்தால், ஃபோன் சூடாகலாம்:\n	• அதிகளவு தரவைப் பயன்படுத்தும் ஆப்ஸை (எ.கா: கேமிங், வீடியோ (அ) வழிகாட்டுதல் பயன்பாடுகள்) பயன்படுத்துவது\n	• பெரிய கோப்புகளைப் பதிவிறக்குவது/பதிவேற்றுவது\n	• அதிக வெப்பநிலையில் ஃபோனைப் பயன்படுத்துவது"</string>
+    <string name="thermal_shutdown_dialog_message" msgid="566347880005304139">"உங்கள் ஃபோன் அதிகமாகச் சூடானதால், அதன் சூட்டைக் குறைக்க, ஆஃப் செய்யப்பட்டது. இப்போது உங்கள் ஃபோன் இயல்புநிலையில் இயங்குகிறது.\n\nபின்வருவனவற்றைச் செய்தால், ஃபோன் சூடாகலாம்:\n	• அதிகளவு தரவைப் பயன்படுத்தும் ஆப்ஸை (எ.கா: கேமிங், வீடியோ (அ) வழிகாட்டுதல் ஆப்ஸ்) பயன்படுத்துவது\n	• பெரிய கோப்புகளைப் பதிவிறக்குவது/பதிவேற்றுவது\n	• அதிக வெப்பநிலையில் ஃபோனைப் பயன்படுத்துவது"</string>
     <string name="high_temp_title" msgid="4589508026407318374">"மொபைல் சூடாகிறது"</string>
     <string name="high_temp_notif_message" msgid="5642466103153429279">"மொபைலின் வெப்ப அளவு குறையும் போது, சில அம்சங்களைப் பயன்படுத்த முடியாது"</string>
     <string name="high_temp_dialog_message" msgid="6840700639374113553">"உங்கள் மொபைலின் வெப்ப அளவு தானாகவே குறையும். தொடர்ந்து நீங்கள் மொபைலைப் பயன்படுத்தலாம், ஆனால் அதன் வேகம் குறைவாக இருக்கக்கூடும்.\n\nமொபைலின் வெப்ப அளவு குறைந்தவுடன், அது இயல்பு நிலையில் இயங்கும்."</string>
@@ -891,7 +909,7 @@
     <string name="qs_dnd_until" msgid="3469471136280079874">"<xliff:g id="ID_1">%s</xliff:g> வரை"</string>
     <string name="qs_dnd_keep" msgid="1825009164681928736">"வைத்திரு"</string>
     <string name="qs_dnd_replace" msgid="8019520786644276623">"மாற்று"</string>
-    <string name="running_foreground_services_title" msgid="381024150898615683">"பின்னணியில் இயங்கும் பயன்பாடுகள்"</string>
+    <string name="running_foreground_services_title" msgid="381024150898615683">"பின்னணியில் இயங்கும் ஆப்ஸ்"</string>
     <string name="running_foreground_services_msg" msgid="6326247670075574355">"பேட்டரி மற்றும் டேட்டா உபயோக விவரங்களைக் காண, தட்டவும்"</string>
     <string name="mobile_data_disable_title" msgid="1068272097382942231">"மொபைல் டேட்டாவை ஆஃப் செய்யவா?"</string>
     <string name="mobile_data_disable_message" msgid="4756541658791493506">"<xliff:g id="CARRIER">%s</xliff:g> மூலம் டேட்டா அல்லது இணையத்தை உங்களால் பயன்படுத்த முடியாது. வைஃபை வழியாக மட்டுமே இணையத்தைப் பயன்படுத்த முடியும்."</string>
diff --git a/packages/SystemUI/res/values-te/strings.xml b/packages/SystemUI/res/values-te/strings.xml
index 62fe95b..c6b2bb7 100644
--- a/packages/SystemUI/res/values-te/strings.xml
+++ b/packages/SystemUI/res/values-te/strings.xml
@@ -47,6 +47,8 @@
     <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_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_accessory_confirm_prompt" msgid="4333670517539993561">"<xliff:g id="USB_ACCESSORY">%2$s</xliff:g>ని నిర్వహించడానికి <xliff:g id="APPLICATION">%1$s</xliff:g>ని తెరవాలా?"</string>
@@ -126,6 +128,20 @@
     <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="face_dialog_looking_for_face" msgid="7049276266074494689">"మీ కోసం చూస్తోంది…"</string>
@@ -364,6 +380,8 @@
     </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_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 eb6810a0..2907524 100644
--- a/packages/SystemUI/res/values-th/strings.xml
+++ b/packages/SystemUI/res/values-th/strings.xml
@@ -47,6 +47,8 @@
     <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_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_accessory_confirm_prompt" msgid="4333670517539993561">"เปิด <xliff:g id="APPLICATION">%1$s</xliff:g> เพื่อจัดการ <xliff:g id="USB_ACCESSORY">%2$s</xliff:g> ไหม"</string>
@@ -126,6 +128,20 @@
     <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="face_dialog_looking_for_face" msgid="7049276266074494689">"กำลังหาใบหน้าคุณ…"</string>
@@ -364,6 +380,8 @@
     </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_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 f6abdcb..ce8c88b 100644
--- a/packages/SystemUI/res/values-tl/strings.xml
+++ b/packages/SystemUI/res/values-tl/strings.xml
@@ -47,6 +47,8 @@
     <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_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_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>
@@ -126,6 +128,20 @@
     <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="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>
@@ -364,6 +380,8 @@
     </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_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 b5e1702..7976014 100644
--- a/packages/SystemUI/res/values-tr/strings.xml
+++ b/packages/SystemUI/res/values-tr/strings.xml
@@ -47,6 +47,8 @@
     <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_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_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>
@@ -126,6 +128,20 @@
     <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="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>
@@ -364,6 +380,8 @@
     </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_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 36bec1e..ea2f376 100644
--- a/packages/SystemUI/res/values-uk/strings.xml
+++ b/packages/SystemUI/res/values-uk/strings.xml
@@ -47,6 +47,8 @@
     <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_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_accessory_confirm_prompt" msgid="4333670517539993561">"Відкрити додаток <xliff:g id="APPLICATION">%1$s</xliff:g>, щоб використовувати такий аксесуар: <xliff:g id="USB_ACCESSORY">%2$s</xliff:g>?"</string>
@@ -126,6 +128,20 @@
     <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="face_dialog_looking_for_face" msgid="7049276266074494689">"Пошук обличчя…"</string>
@@ -368,6 +384,8 @@
     </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_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 5fceabe..1c28431 100644
--- a/packages/SystemUI/res/values-ur/strings.xml
+++ b/packages/SystemUI/res/values-ur/strings.xml
@@ -47,6 +47,8 @@
     <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_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_accessory_confirm_prompt" msgid="4333670517539993561">"<xliff:g id="USB_ACCESSORY">%2$s</xliff:g> ہینڈل کرنے کیلئے <xliff:g id="APPLICATION">%1$s</xliff:g> کھولیں؟"</string>
@@ -126,6 +128,20 @@
     <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="face_dialog_looking_for_face" msgid="7049276266074494689">"آپ کے لیے تلاش کیا جا رہا ہے…"</string>
@@ -364,6 +380,8 @@
     </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_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 37651a5..c3e39e5 100644
--- a/packages/SystemUI/res/values-uz/strings.xml
+++ b/packages/SystemUI/res/values-uz/strings.xml
@@ -47,6 +47,8 @@
     <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_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_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>
@@ -126,6 +128,20 @@
     <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="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>
@@ -364,6 +380,8 @@
     </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_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 f678265..d2da39b 100644
--- a/packages/SystemUI/res/values-vi/strings.xml
+++ b/packages/SystemUI/res/values-vi/strings.xml
@@ -47,6 +47,8 @@
     <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_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_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>
@@ -56,7 +58,7 @@
     <string name="always_use_device" msgid="4015357883336738417">"Luôn mở <xliff:g id="APPLICATION">%1$s</xliff:g> khi kết nối <xliff:g id="USB_DEVICE">%2$s</xliff:g>"</string>
     <string name="always_use_accessory" msgid="3257892669444535154">"Luôn mở <xliff:g id="APPLICATION">%1$s</xliff:g> khi kết nối <xliff:g id="USB_ACCESSORY">%2$s</xliff:g>"</string>
     <string name="usb_debugging_title" msgid="4513918393387141949">"Cho phép gỡ lỗi qua USB?"</string>
-    <string name="usb_debugging_message" msgid="2220143855912376496">"Tệp tham chiếu khóa RSA của máy tính là:\n<xliff:g id="FINGERPRINT">%1$s</xliff:g>"</string>
+    <string name="usb_debugging_message" msgid="2220143855912376496">"Vân tay khóa RSA của máy tính là:\n<xliff:g id="FINGERPRINT">%1$s</xliff:g>"</string>
     <string name="usb_debugging_always" msgid="303335496705863070">"Luôn cho phép từ máy tính này"</string>
     <string name="usb_debugging_allow" msgid="2272145052073254852">"Cho phép"</string>
     <string name="usb_debugging_secondary_user_title" msgid="6353808721761220421">"Không cho phép chế độ gỡ lỗi qua USB"</string>
@@ -126,6 +128,20 @@
     <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="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>
@@ -364,6 +380,8 @@
     </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_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 05509f6..551e54e 100644
--- a/packages/SystemUI/res/values-zh-rCN/strings.xml
+++ b/packages/SystemUI/res/values-zh-rCN/strings.xml
@@ -47,6 +47,8 @@
     <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_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_accessory_confirm_prompt" msgid="4333670517539993561">"要打开<xliff:g id="APPLICATION">%1$s</xliff:g>来处理<xliff:g id="USB_ACCESSORY">%2$s</xliff:g>吗?"</string>
@@ -126,6 +128,20 @@
     <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="face_dialog_looking_for_face" msgid="7049276266074494689">"正在查找您的面孔…"</string>
@@ -364,6 +380,8 @@
     </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_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 b57e61f..206fcfc 100644
--- a/packages/SystemUI/res/values-zh-rHK/strings.xml
+++ b/packages/SystemUI/res/values-zh-rHK/strings.xml
@@ -47,6 +47,8 @@
     <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_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_accessory_confirm_prompt" msgid="4333670517539993561">"要開啟「<xliff:g id="APPLICATION">%1$s</xliff:g>」處理「<xliff:g id="USB_ACCESSORY">%2$s</xliff:g>」嗎?"</string>
@@ -126,6 +128,20 @@
     <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="face_dialog_looking_for_face" msgid="7049276266074494689">"正在搜尋您的臉孔…"</string>
@@ -364,6 +380,8 @@
     </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_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 14fedbb..c1f299d 100644
--- a/packages/SystemUI/res/values-zh-rTW/strings.xml
+++ b/packages/SystemUI/res/values-zh-rTW/strings.xml
@@ -47,6 +47,8 @@
     <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_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_accessory_confirm_prompt" msgid="4333670517539993561">"要開啟「<xliff:g id="APPLICATION">%1$s</xliff:g>」處理「<xliff:g id="USB_ACCESSORY">%2$s</xliff:g>」嗎?"</string>
@@ -126,6 +128,20 @@
     <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="face_dialog_looking_for_face" msgid="7049276266074494689">"正在尋找你的臉孔…"</string>
@@ -364,6 +380,8 @@
     </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_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 c158c77..37eca51 100644
--- a/packages/SystemUI/res/values-zu/strings.xml
+++ b/packages/SystemUI/res/values-zu/strings.xml
@@ -47,6 +47,8 @@
     <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_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_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>
@@ -126,6 +128,20 @@
     <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="accessibility_fingerprint_dialog_fingerprint_icon" msgid="3125122495414253226">"Isithonjana sezigxivizo zeminwe"</string>
     <string name="face_dialog_looking_for_face" msgid="7049276266074494689">"Kufunwa wena…"</string>
@@ -364,6 +380,8 @@
     </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_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 61210d3..105b27e 100644
--- a/packages/SystemUI/res/values/config.xml
+++ b/packages/SystemUI/res/values/config.xml
@@ -279,7 +279,7 @@
         <item>com.android.systemui.recents.Recents</item>
         <item>com.android.systemui.volume.VolumeUI</item>
         <item>com.android.systemui.stackdivider.Divider</item>
-        <item>com.android.systemui.SystemBars</item>
+        <item>com.android.systemui.statusbar.phone.StatusBar</item>
         <item>com.android.systemui.usb.StorageNotification</item>
         <item>com.android.systemui.power.PowerUI</item>
         <item>com.android.systemui.media.RingtonePlayer</item>
diff --git a/packages/SystemUI/res/values/dimens.xml b/packages/SystemUI/res/values/dimens.xml
index 1079206..d722d61 100644
--- a/packages/SystemUI/res/values/dimens.xml
+++ b/packages/SystemUI/res/values/dimens.xml
@@ -1009,10 +1009,15 @@
     <!-- Biometric Dialog values -->
     <dimen name="biometric_dialog_biometric_icon_size">64dp</dimen>
     <dimen name="biometric_dialog_corner_size">4dp</dimen>
+    <!-- Y translation when showing/dismissing the dialog-->
     <dimen name="biometric_dialog_animation_translation_offset">350dp</dimen>
     <dimen name="biometric_dialog_border_padding">4dp</dimen>
     <dimen name="biometric_dialog_elevation">1dp</dimen>
     <dimen name="biometric_dialog_icon_padding">16dp</dimen>
+    <!-- Y translation for biometric contents when transitioning to device credential UI -->
+    <dimen name="biometric_dialog_medium_to_large_translation_offset">100dp</dimen>
+    <!-- Y translation for credential contents when animating in -->
+    <dimen name="biometric_dialog_credential_translation_offset">60dp</dimen>
 
     <!-- Wireless Charging Animation values -->
     <dimen name="wireless_charging_dots_radius_start">0dp</dimen>
diff --git a/packages/SystemUI/res/values/ids.xml b/packages/SystemUI/res/values/ids.xml
index 3727181..04640f4 100644
--- a/packages/SystemUI/res/values/ids.xml
+++ b/packages/SystemUI/res/values/ids.xml
@@ -141,5 +141,8 @@
 
     <!-- Global Actions Menu -->
     <item type="id" name="global_actions_view" />
+
+    <!-- NotificationPanelView -->
+    <item type="id" name="notification_panel" />
 </resources>
 
diff --git a/packages/SystemUI/res/values/strings.xml b/packages/SystemUI/res/values/strings.xml
index 97e2f0f..8335c11 100644
--- a/packages/SystemUI/res/values/strings.xml
+++ b/packages/SystemUI/res/values/strings.xml
@@ -118,10 +118,13 @@
     <string name="status_bar_use_physical_keyboard">Physical keyboard</string>
 
     <!-- Prompt for the USB device permission dialog [CHAR LIMIT=80] -->
-    <string name="usb_device_permission_prompt">Allow <xliff:g id="application">%1$s</xliff:g> to access <xliff:g id="usb_device">%2$s</xliff:g>?</string>
+    <string name="usb_device_permission_prompt">Allow <xliff:g id="application" example= "Usb Mega Player">%1$s</xliff:g> to access <xliff:g id="usb_device" example="USB Headphones">%2$s</xliff:g>?</string>
+
+    <!-- Checkbox label for USB device dialogs with warning text for USB device dialogs.  [CHAR LIMIT=200]-->
+    <string name="usb_device_permission_prompt_warn">Allow <xliff:g id="application" example= "Usb Mega Player">%1$s</xliff:g> to access <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 permission dialog [CHAR LIMIT=80] -->
-    <string name="usb_accessory_permission_prompt">Allow <xliff:g id="application">%1$s</xliff:g> to access <xliff:g id="usb_accessory">%2$s</xliff:g>?</string>
+    <string name="usb_accessory_permission_prompt">Allow <xliff:g id="application" example= "Usb Mega Player">%1$s</xliff:g> to access <xliff:g id="usb_accessory"  example="USB Dock">%2$s</xliff:g>?</string>
 
     <!-- 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>
@@ -308,6 +311,21 @@
     <!-- Talkback string when a biometric is authenticated [CHAR LIMIT=NONE] -->
     <string name="biometric_dialog_authenticated">Authenticated</string>
 
+    <!-- Button text shown on BiometricPrompt giving the user the option to use an alternate form of authentication (Pin) [CHAR LIMIT=30] -->
+    <string name="biometric_dialog_use_pin">Use PIN</string>
+    <!-- Button text shown on BiometricPrompt giving the user the option to use an alternate form of authentication (Pattern) [CHAR LIMIT=30] -->
+    <string name="biometric_dialog_use_pattern">Use pattern</string>
+    <!-- Button text shown on BiometricPrompt giving the user the option to use an alternate form of authentication (Pass) [CHAR LIMIT=30] -->
+    <string name="biometric_dialog_use_password">Use password</string>
+    <!-- Error string shown when the user enters an incorrect PIN [CHAR LIMIT=40]-->
+    <string name="biometric_dialog_wrong_pin">Wrong PIN</string>
+    <!-- Error string shown when the user enters an incorrect pattern [CHAR LIMIT=40]-->
+    <string name="biometric_dialog_wrong_pattern">Wrong pattern</string>
+    <!-- Error string shown when the user enters an incorrect password [CHAR LIMIT=40]-->
+    <string name="biometric_dialog_wrong_password">Wrong password</string>
+    <!-- Error string shown when the user enters too many incorrect attempts [CHAR LIMIT=120]-->
+    <string name="biometric_dialog_credential_too_many_attempts">Too many incorrect attempts.\nTry again in <xliff:g id="number">%d</xliff:g> seconds.</string>
+
     <!-- Message shown when the system-provided fingerprint dialog is shown, asking for authentication -->
     <string name="fingerprint_dialog_touch_sensor">Touch the fingerprint sensor</string>
     <!-- Content description of the fingerprint icon when the system-provided fingerprint dialog is showing, for accessibility (not shown on the screen). [CHAR LIMIT=NONE] -->
@@ -860,6 +878,8 @@
     <string name="quick_settings_notifications_label">Notifications</string>
     <!-- QuickSettings: Flashlight [CHAR LIMIT=NONE] -->
     <string name="quick_settings_flashlight_label">Flashlight</string>
+    <!-- QuickSettings: Flashlight, used when it's not available due to camera in use [CHAR LIMIT=NONE] -->
+    <string name="quick_settings_flashlight_camera_in_use">Camera in use</string>
     <!-- QuickSettings: Cellular detail panel title [CHAR LIMIT=NONE] -->
     <string name="quick_settings_cellular_detail_title">Mobile data</string>
     <!-- QuickSettings: Cellular detail panel, data usage title [CHAR LIMIT=NONE] -->
diff --git a/packages/SystemUI/res/values/styles.xml b/packages/SystemUI/res/values/styles.xml
index 6374191..96fbcbb 100644
--- a/packages/SystemUI/res/values/styles.xml
+++ b/packages/SystemUI/res/values/styles.xml
@@ -314,6 +314,12 @@
         <item name="*android:errorColor">?android:attr/colorError</item>
     </style>
 
+    <style name="LockPatternStyleBiometricPrompt">
+        <item name="*android:regularColor">?android:attr/colorForeground</item>
+        <item name="*android:successColor">?android:attr/colorForeground</item>
+        <item name="*android:errorColor">?android:attr/colorError</item>
+    </style>
+
     <style name="qs_theme" parent="@*android:style/Theme.DeviceDefault.QuickSettings">
         <item name="lightIconTheme">@style/QSIconTheme</item>
         <item name="darkIconTheme">@style/QSIconTheme</item>
diff --git a/packages/SystemUI/shared/src/com/android/systemui/shared/system/TaskStackChangeListener.java b/packages/SystemUI/shared/src/com/android/systemui/shared/system/TaskStackChangeListener.java
index 5ddf89c..6186589 100644
--- a/packages/SystemUI/shared/src/com/android/systemui/shared/system/TaskStackChangeListener.java
+++ b/packages/SystemUI/shared/src/com/android/systemui/shared/system/TaskStackChangeListener.java
@@ -17,6 +17,7 @@
 package com.android.systemui.shared.system;
 
 import android.app.ActivityManager.RunningTaskInfo;
+import android.app.ITaskStackListener;
 import android.content.ComponentName;
 import android.os.IBinder;
 import android.os.UserHandle;
@@ -106,6 +107,9 @@
      */
     public void onRecentTaskListUpdated() { }
 
+    /** @see ITaskStackListener#onRecentTaskListFrozenChanged(boolean) */
+    public void onRecentTaskListFrozenChanged(boolean frozen) { }
+
     /**
      * Checks that the current user matches the process. Since
      * {@link android.app.ITaskStackListener} is not multi-user aware, handlers of
diff --git a/packages/SystemUI/shared/src/com/android/systemui/shared/system/TaskStackChangeListeners.java b/packages/SystemUI/shared/src/com/android/systemui/shared/system/TaskStackChangeListeners.java
index 820057a..8d823ca 100644
--- a/packages/SystemUI/shared/src/com/android/systemui/shared/system/TaskStackChangeListeners.java
+++ b/packages/SystemUI/shared/src/com/android/systemui/shared/system/TaskStackChangeListeners.java
@@ -224,6 +224,12 @@
         mHandler.obtainMessage(H.ON_TASK_LIST_UPDATED).sendToTarget();
     }
 
+    @Override
+    public void onRecentTaskListFrozenChanged(boolean frozen) {
+        mHandler.obtainMessage(H.ON_TASK_LIST_FROZEN_UNFROZEN, frozen ? 1 : 0, 0 /* unused */)
+                .sendToTarget();
+    }
+
     private final class H extends Handler {
         private static final int ON_TASK_STACK_CHANGED = 1;
         private static final int ON_TASK_SNAPSHOT_CHANGED = 2;
@@ -247,6 +253,7 @@
         private static final int ON_TASK_DISPLAY_CHANGED = 20;
         private static final int ON_TASK_LIST_UPDATED = 21;
         private static final int ON_SINGLE_TASK_DISPLAY_EMPTY = 22;
+        private static final int ON_TASK_LIST_FROZEN_UNFROZEN = 23;
 
 
         public H(Looper looper) {
@@ -408,6 +415,12 @@
                         }
                         break;
                     }
+                    case ON_TASK_LIST_FROZEN_UNFROZEN: {
+                        for (int i = mTaskStackListeners.size() - 1; i >= 0; i--) {
+                            mTaskStackListeners.get(i).onRecentTaskListFrozenChanged(msg.arg1 != 0);
+                        }
+                        break;
+                    }
                 }
             }
         }
diff --git a/packages/SystemUI/shared/src/com/android/systemui/shared/system/WindowManagerWrapper.java b/packages/SystemUI/shared/src/com/android/systemui/shared/system/WindowManagerWrapper.java
index ad182fe..22d1675c 100644
--- a/packages/SystemUI/shared/src/com/android/systemui/shared/system/WindowManagerWrapper.java
+++ b/packages/SystemUI/shared/src/com/android/systemui/shared/system/WindowManagerWrapper.java
@@ -53,7 +53,6 @@
     public static final int TRANSIT_WALLPAPER_INTRA_CLOSE =
             WindowManager.TRANSIT_WALLPAPER_INTRA_CLOSE;
     public static final int TRANSIT_TASK_OPEN_BEHIND = WindowManager.TRANSIT_TASK_OPEN_BEHIND;
-    public static final int TRANSIT_TASK_IN_PLACE = WindowManager.TRANSIT_TASK_IN_PLACE;
     public static final int TRANSIT_ACTIVITY_RELAUNCH = WindowManager.TRANSIT_ACTIVITY_RELAUNCH;
     public static final int TRANSIT_DOCK_TASK_FROM_RECENTS =
             WindowManager.TRANSIT_DOCK_TASK_FROM_RECENTS;
diff --git a/packages/SystemUI/src/com/android/keyguard/CarrierTextController.java b/packages/SystemUI/src/com/android/keyguard/CarrierTextController.java
index 949941b..46b4c6b 100644
--- a/packages/SystemUI/src/com/android/keyguard/CarrierTextController.java
+++ b/packages/SystemUI/src/com/android/keyguard/CarrierTextController.java
@@ -35,6 +35,7 @@
 import android.text.TextUtils;
 import android.util.Log;
 
+import androidx.annotation.Nullable;
 import androidx.annotation.VisibleForTesting;
 
 import com.android.internal.telephony.IccCardConstants;
@@ -57,6 +58,7 @@
     private static final String TAG = "CarrierTextController";
 
     private final boolean mIsEmergencyCallCapable;
+    private final Handler mMainHandler;
     private boolean mTelephonyCapable;
     private boolean mShowMissingSim;
     private boolean mShowAirplaneMode;
@@ -65,6 +67,7 @@
     private WifiManager mWifiManager;
     private boolean[] mSimErrorState;
     private final int mSimSlotsNumber;
+    @Nullable // Check for nullability before dispatching
     private CarrierTextCallback mCarrierTextCallback;
     private Context mContext;
     private CharSequence mSeparator;
@@ -73,12 +76,12 @@
             new WakefulnessLifecycle.Observer() {
                 @Override
                 public void onFinishedWakingUp() {
-                    mCarrierTextCallback.finishedWakingUp();
+                    if (mCarrierTextCallback != null) mCarrierTextCallback.finishedWakingUp();
                 }
 
                 @Override
                 public void onStartedGoingToSleep() {
-                    mCarrierTextCallback.startedGoingToSleep();
+                    if (mCarrierTextCallback != null) mCarrierTextCallback.startedGoingToSleep();
                 }
             };
 
@@ -167,8 +170,9 @@
         mSeparator = separator;
         mWakefulnessLifecycle = Dependency.get(WakefulnessLifecycle.class);
         mSimSlotsNumber = ((TelephonyManager) context.getSystemService(
-                Context.TELEPHONY_SERVICE)).getMaxPhoneCount();
+                Context.TELEPHONY_SERVICE)).getSupportedModemCount();
         mSimErrorState = new boolean[mSimSlotsNumber];
+        mMainHandler = Dependency.get(Dependency.MAIN_HANDLER);
     }
 
     /**
@@ -227,7 +231,12 @@
             if (whitelistIpcs(() -> ConnectivityManager.from(mContext).isNetworkSupported(
                     ConnectivityManager.TYPE_MOBILE))) {
                 mKeyguardUpdateMonitor = Dependency.get(KeyguardUpdateMonitor.class);
-                mKeyguardUpdateMonitor.registerCallback(mCallback);
+                // Keyguard update monitor expects callbacks from main thread
+                mMainHandler.post(() -> {
+                    if (mKeyguardUpdateMonitor != null) {
+                        mKeyguardUpdateMonitor.registerCallback(mCallback);
+                    }
+                });
                 mWakefulnessLifecycle.addObserver(mWakefulnessObserver);
                 telephonyManager.listen(mPhoneStateListener,
                         LISTEN_ACTIVE_DATA_SUBSCRIPTION_ID_CHANGE);
@@ -239,7 +248,12 @@
         } else {
             mCarrierTextCallback = null;
             if (mKeyguardUpdateMonitor != null) {
-                mKeyguardUpdateMonitor.removeCallback(mCallback);
+                // Keyguard update monitor expects callbacks from main thread
+                mMainHandler.post(() -> {
+                    if (mKeyguardUpdateMonitor != null) {
+                        mKeyguardUpdateMonitor.removeCallback(mCallback);
+                    }
+                });
                 mWakefulnessLifecycle.removeObserver(mWakefulnessObserver);
             }
             telephonyManager.listen(mPhoneStateListener, LISTEN_NONE);
@@ -364,10 +378,9 @@
 
     @VisibleForTesting
     protected void postToCallback(CarrierTextCallbackInfo info) {
-        Handler handler = Dependency.get(Dependency.MAIN_HANDLER);
         final CarrierTextCallback callback = mCarrierTextCallback;
         if (callback != null) {
-            handler.post(() -> callback.updateCarrierInfo(info));
+            mMainHandler.post(() -> callback.updateCarrierInfo(info));
         }
     }
 
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityContainer.java b/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityContainer.java
index 8d167e8..b9fe933 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityContainer.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityContainer.java
@@ -76,7 +76,7 @@
     // How much you need to drag the bouncer to trigger an auth retry (in dps.)
     private static final float MIN_DRAG_SIZE = 10;
     // How much to scale the default slop by, to avoid accidental drags.
-    private static final float SLOP_SCALE = 2f;
+    private static final float SLOP_SCALE = 4f;
 
     private KeyguardSecurityModel mSecurityModel;
     private LockPatternUtils mLockPatternUtils;
@@ -128,7 +128,7 @@
 
     public KeyguardSecurityContainer(Context context, AttributeSet attrs, int defStyle) {
         super(context, attrs, defStyle);
-        mSecurityModel = new KeyguardSecurityModel(context);
+        mSecurityModel = Dependency.get(KeyguardSecurityModel.class);
         mLockPatternUtils = new LockPatternUtils(context);
         mUpdateMonitor = Dependency.get(KeyguardUpdateMonitor.class);
         mSpringAnimation = new SpringAnimation(this, DynamicAnimation.Y);
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityModel.java b/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityModel.java
index bb89959..1395fd9 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityModel.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityModel.java
@@ -25,6 +25,10 @@
 import com.android.internal.widget.LockPatternUtils;
 import com.android.systemui.Dependency;
 
+import javax.inject.Inject;
+import javax.inject.Singleton;
+
+@Singleton
 public class KeyguardSecurityModel {
 
     /**
@@ -46,6 +50,7 @@
 
     private LockPatternUtils mLockPatternUtils;
 
+    @Inject
     KeyguardSecurityModel(Context context) {
         mContext = context;
         mLockPatternUtils = new LockPatternUtils(context);
@@ -57,7 +62,7 @@
         mLockPatternUtils = utils;
     }
 
-    SecurityMode getSecurityMode(int userId) {
+    public SecurityMode getSecurityMode(int userId) {
         KeyguardUpdateMonitor monitor = Dependency.get(KeyguardUpdateMonitor.class);
 
         if (mIsPukScreenAvailable && SubscriptionManager.isValidSubscriptionId(
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardStatusView.java b/packages/SystemUI/src/com/android/keyguard/KeyguardStatusView.java
index 63da533..5a1c997 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardStatusView.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardStatusView.java
@@ -22,7 +22,6 @@
 import android.content.res.Resources;
 import android.graphics.Color;
 import android.os.Handler;
-import android.os.Looper;
 import android.os.RemoteException;
 import android.os.UserHandle;
 import android.text.TextUtils;
@@ -135,7 +134,7 @@
         super(context, attrs, defStyle);
         mIActivityManager = ActivityManager.getService();
         mLockPatternUtils = new LockPatternUtils(getContext());
-        mHandler = new Handler(Looper.myLooper());
+        mHandler = new Handler();
         onDensityOrFontScaleChanged();
     }
 
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java b/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java
index a6b3be2..ac5e255 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java
@@ -58,6 +58,7 @@
 import android.content.pm.IPackageManager;
 import android.content.pm.PackageManager;
 import android.content.pm.ResolveInfo;
+import android.content.pm.UserInfo;
 import android.database.ContentObserver;
 import android.hardware.biometrics.BiometricManager;
 import android.hardware.biometrics.BiometricSourceType;
@@ -98,6 +99,7 @@
 import com.android.internal.telephony.TelephonyIntents;
 import com.android.internal.widget.LockPatternUtils;
 import com.android.settingslib.WirelessUtils;
+import com.android.systemui.DejankUtils;
 import com.android.systemui.R;
 import com.android.systemui.shared.system.ActivityManagerWrapper;
 import com.android.systemui.shared.system.TaskStackChangeListener;
@@ -117,12 +119,14 @@
 
 import javax.inject.Inject;
 import javax.inject.Named;
+import javax.inject.Singleton;
 
 /**
  * Watches for updates that may be interesting to the keyguard, and provides
  * the up to date information as well as a registration for callbacks that care
  * to be updated.
  */
+@Singleton
 public class KeyguardUpdateMonitor implements TrustManager.TrustListener {
 
     private static final String TAG = "KeyguardUpdateMonitor";
@@ -329,6 +333,7 @@
     private SparseBooleanArray mUserIsUnlocked = new SparseBooleanArray();
     private SparseBooleanArray mUserHasTrust = new SparseBooleanArray();
     private SparseBooleanArray mUserTrustIsManaged = new SparseBooleanArray();
+    private SparseBooleanArray mUserTrustIsUsuallyManaged = new SparseBooleanArray();
     private SparseBooleanArray mUserFingerprintAuthenticated = new SparseBooleanArray();
     private SparseBooleanArray mUserFaceAuthenticated = new SparseBooleanArray();
     private SparseBooleanArray mUserFaceUnlockRunning = new SparseBooleanArray();
@@ -472,6 +477,7 @@
     public void onTrustManagedChanged(boolean managed, int userId) {
         checkIsHandlerThread();
         mUserTrustIsManaged.put(userId, managed);
+        mUserTrustIsUsuallyManaged.put(userId, mTrustManager.isTrustUsuallyManaged(userId));
         for (int i = 0; i < mCallbacks.size(); i++) {
             KeyguardUpdateMonitorCallback cb = mCallbacks.get(i).get();
             if (cb != null) {
@@ -925,6 +931,14 @@
         return mUserTrustIsManaged.get(userId) && !isTrustDisabled(userId);
     }
 
+    /**
+     * Cached version of {@link TrustManager#isTrustUsuallyManaged(int)}.
+     */
+    public boolean isTrustUsuallyManaged(int userId) {
+        checkIsHandlerThread();
+        return mUserTrustIsUsuallyManaged.get(userId);
+    }
+
     public boolean isUnlockingWithBiometricAllowed() {
         return mStrongAuthTracker.isUnlockingWithBiometricAllowed();
     }
@@ -1424,6 +1438,8 @@
     }
 
     private void handleScreenTurnedOff() {
+        final String tag = "KeyguardUpdateMonitor#handleScreenTurnedOff";
+        DejankUtils.startDetectingBlockingIpcs(tag);
         checkIsHandlerThread();
         mHardwareFingerprintUnavailableRetryCount = 0;
         mHardwareFaceUnavailableRetryCount = 0;
@@ -1433,6 +1449,7 @@
                 cb.onScreenTurnedOff();
             }
         }
+        DejankUtils.stopDetectingBlockingIpcs(tag);
     }
 
     private void handleDreamingStateChanged(int dreamStart) {
@@ -1474,9 +1491,11 @@
         mUserIsUnlocked.put(userId, mUserManager.isUserUnlocked(userId));
     }
 
-    private void handleUserRemoved(int userId) {
+    @VisibleForTesting
+    void handleUserRemoved(int userId) {
         checkIsHandlerThread();
         mUserIsUnlocked.delete(userId);
+        mUserTrustIsUsuallyManaged.delete(userId);
     }
 
     @VisibleForTesting
@@ -1662,7 +1681,7 @@
             e.rethrowAsRuntimeException();
         }
 
-        mTrustManager = (TrustManager) context.getSystemService(Context.TRUST_SERVICE);
+        mTrustManager = context.getSystemService(TrustManager.class);
         mTrustManager.registerTrustListener(this);
         mLockPatternUtils = new LockPatternUtils(context);
         mLockPatternUtils.registerStrongAuthTracker(mStrongAuthTracker);
@@ -1697,6 +1716,11 @@
         mUserIsUnlocked.put(user, mUserManager.isUserUnlocked(user));
         mDevicePolicyManager = context.getSystemService(DevicePolicyManager.class);
         mLogoutEnabled = mDevicePolicyManager.isLogoutEnabled();
+        List<UserInfo> allUsers = mUserManager.getUsers();
+        for (UserInfo userInfo : allUsers) {
+            mUserTrustIsUsuallyManaged.put(userInfo.id,
+                    mTrustManager.isTrustUsuallyManaged(userInfo.id));
+        }
         updateAirplaneModeState();
 
         TelephonyManager telephony =
@@ -2048,6 +2072,7 @@
      */
     private void handleUserSwitching(int userId, IRemoteCallback reply) {
         checkIsHandlerThread();
+        mUserTrustIsUsuallyManaged.put(userId, mTrustManager.isTrustUsuallyManaged(userId));
         for (int i = 0; i < mCallbacks.size(); i++) {
             KeyguardUpdateMonitorCallback cb = mCallbacks.get(i).get();
             if (cb != null) {
diff --git a/packages/SystemUI/src/com/android/systemui/Dependency.java b/packages/SystemUI/src/com/android/systemui/Dependency.java
index 37bb54c..07bfa71 100644
--- a/packages/SystemUI/src/com/android/systemui/Dependency.java
+++ b/packages/SystemUI/src/com/android/systemui/Dependency.java
@@ -30,6 +30,7 @@
 import com.android.internal.logging.MetricsLogger;
 import com.android.internal.statusbar.IStatusBarService;
 import com.android.internal.util.Preconditions;
+import com.android.keyguard.KeyguardSecurityModel;
 import com.android.keyguard.KeyguardUpdateMonitor;
 import com.android.keyguard.clock.ClockManager;
 import com.android.settingslib.bluetooth.LocalBluetoothManager;
@@ -316,6 +317,7 @@
     @Inject Lazy<FalsingManager> mFalsingManager;
     @Inject Lazy<SysUiState> mSysUiStateFlagsContainer;
     @Inject Lazy<AlarmManager> mAlarmManager;
+    @Inject Lazy<KeyguardSecurityModel> mKeyguardSecurityModel;
 
     @Inject
     public Dependency() {
@@ -501,6 +503,7 @@
         mProviders.put(FalsingManager.class, mFalsingManager::get);
         mProviders.put(SysUiState.class, mSysUiStateFlagsContainer::get);
         mProviders.put(AlarmManager.class, mAlarmManager::get);
+        mProviders.put(KeyguardSecurityModel.class, mKeyguardSecurityModel::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/DependencyBinder.java b/packages/SystemUI/src/com/android/systemui/DependencyBinder.java
index c4dce1e..f9f0f1b 100644
--- a/packages/SystemUI/src/com/android/systemui/DependencyBinder.java
+++ b/packages/SystemUI/src/com/android/systemui/DependencyBinder.java
@@ -200,6 +200,12 @@
     /**
      */
     @Binds
+    public abstract SysuiStatusBarStateController providesSysuiStatusBarStateController(
+            StatusBarStateControllerImpl statusBarStateControllerImpl);
+
+    /**
+     */
+    @Binds
     public abstract StatusBarIconController provideStatusBarIconController(
             StatusBarIconControllerImpl controllerImpl);
 
@@ -235,10 +241,4 @@
      */
     @Binds
     public abstract FalsingManager provideFalsingmanager(FalsingManagerProxy falsingManagerImpl);
-
-    /**
-     */
-    @Binds
-    public abstract SysuiStatusBarStateController providesSysuiStatusBarStateController(
-            StatusBarStateControllerImpl statusBarStateControllerImpl);
 }
diff --git a/packages/SystemUI/src/com/android/systemui/DependencyProvider.java b/packages/SystemUI/src/com/android/systemui/DependencyProvider.java
index 239cbfe..cf199c5 100644
--- a/packages/SystemUI/src/com/android/systemui/DependencyProvider.java
+++ b/packages/SystemUI/src/com/android/systemui/DependencyProvider.java
@@ -40,6 +40,7 @@
 
 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.plugins.PluginInitializerImpl;
 import com.android.systemui.shared.plugins.PluginManager;
@@ -48,6 +49,7 @@
 import com.android.systemui.shared.system.DevicePolicyManagerWrapper;
 import com.android.systemui.shared.system.PackageManagerWrapper;
 import com.android.systemui.statusbar.NavigationBarController;
+import com.android.systemui.statusbar.NotificationRemoteInputManager;
 import com.android.systemui.statusbar.phone.AutoHideController;
 import com.android.systemui.statusbar.phone.ConfigurationControllerImpl;
 import com.android.systemui.statusbar.policy.ConfigurationController;
@@ -203,8 +205,11 @@
     @Singleton
     @Provides
     public AutoHideController provideAutoHideController(Context context,
-            @Named(MAIN_HANDLER_NAME) Handler mainHandler) {
-        return new AutoHideController(context, mainHandler);
+            @Named(MAIN_HANDLER_NAME) Handler mainHandler,
+            NotificationRemoteInputManager notificationRemoteInputManager,
+            IWindowManager iWindowManager) {
+        return new AutoHideController(context, mainHandler, notificationRemoteInputManager,
+                iWindowManager);
     }
 
     @Singleton
@@ -238,4 +243,10 @@
     public AlarmManager provideAlarmManager(Context context) {
         return context.getSystemService(AlarmManager.class);
     }
+
+    /** */
+    @Provides
+    public LockPatternUtils provideLockPatternUtils(Context context) {
+        return new LockPatternUtils(context);
+    }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/ForegroundServiceLifetimeExtender.java b/packages/SystemUI/src/com/android/systemui/ForegroundServiceLifetimeExtender.java
index 0e079e3..5c561e5 100644
--- a/packages/SystemUI/src/com/android/systemui/ForegroundServiceLifetimeExtender.java
+++ b/packages/SystemUI/src/com/android/systemui/ForegroundServiceLifetimeExtender.java
@@ -83,7 +83,9 @@
                 }
             }
         };
-        mHandler.postDelayed(r, MIN_FGS_TIME_MS);
+        long delayAmt = MIN_FGS_TIME_MS
+                - (System.currentTimeMillis() - entry.notification.getPostTime());
+        mHandler.postDelayed(r, delayAmt);
     }
 }
 
diff --git a/packages/SystemUI/src/com/android/systemui/LatencyTester.java b/packages/SystemUI/src/com/android/systemui/LatencyTester.java
index 50f1b44..ddbabee 100644
--- a/packages/SystemUI/src/com/android/systemui/LatencyTester.java
+++ b/packages/SystemUI/src/com/android/systemui/LatencyTester.java
@@ -41,6 +41,10 @@
     private static final String ACTION_TURN_ON_SCREEN =
             "com.android.systemui.latency.ACTION_TURN_ON_SCREEN";
 
+    public LatencyTester(Context context) {
+        super(context);
+    }
+
     @Override
     public void start() {
         if (!Build.IS_DEBUGGABLE) {
diff --git a/packages/SystemUI/src/com/android/systemui/ScreenDecorations.java b/packages/SystemUI/src/com/android/systemui/ScreenDecorations.java
index 3e068b0..3a7a7f7 100644
--- a/packages/SystemUI/src/com/android/systemui/ScreenDecorations.java
+++ b/packages/SystemUI/src/com/android/systemui/ScreenDecorations.java
@@ -132,12 +132,15 @@
         return result;
     }
 
+    public ScreenDecorations(Context context) {
+        super(context);
+    }
+
     @Override
     public void start() {
         mHandler = startHandlerThread();
         mHandler.post(this::startOnScreenDecorationsThread);
         setupStatusBarPaddingIfNeeded();
-        putComponent(ScreenDecorations.class, this);
     }
 
     @VisibleForTesting
diff --git a/packages/SystemUI/src/com/android/systemui/ServiceBinder.java b/packages/SystemUI/src/com/android/systemui/ServiceBinder.java
index e761a2b..e61268e 100644
--- a/packages/SystemUI/src/com/android/systemui/ServiceBinder.java
+++ b/packages/SystemUI/src/com/android/systemui/ServiceBinder.java
@@ -19,6 +19,7 @@
 import android.app.Service;
 
 import com.android.systemui.doze.DozeService;
+import com.android.systemui.keyguard.KeyguardService;
 
 import dagger.Binds;
 import dagger.Module;
@@ -30,8 +31,15 @@
  */
 @Module
 public abstract class ServiceBinder {
+    /** */
     @Binds
     @IntoMap
     @ClassKey(DozeService.class)
     public abstract Service bindDozeService(DozeService 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 c54f6306..a8591bb 100644
--- a/packages/SystemUI/src/com/android/systemui/SizeCompatModeActivityController.java
+++ b/packages/SystemUI/src/com/android/systemui/SizeCompatModeActivityController.java
@@ -59,12 +59,13 @@
     /** Only show once automatically in the process life. */
     private boolean mHasShownHint;
 
-    public SizeCompatModeActivityController() {
-        this(ActivityManagerWrapper.getInstance());
+    public SizeCompatModeActivityController(Context context) {
+        this(context, ActivityManagerWrapper.getInstance());
     }
 
     @VisibleForTesting
-    SizeCompatModeActivityController(ActivityManagerWrapper am) {
+    SizeCompatModeActivityController(Context context, ActivityManagerWrapper am) {
+        super(context);
         am.registerTaskStackListener(new TaskStackChangeListener() {
             @Override
             public void onSizeCompatModeActivityChanged(int displayId, IBinder activityToken) {
diff --git a/packages/SystemUI/src/com/android/systemui/SliceBroadcastRelayHandler.java b/packages/SystemUI/src/com/android/systemui/SliceBroadcastRelayHandler.java
index b3fc69e..92fbd25 100644
--- a/packages/SystemUI/src/com/android/systemui/SliceBroadcastRelayHandler.java
+++ b/packages/SystemUI/src/com/android/systemui/SliceBroadcastRelayHandler.java
@@ -39,6 +39,10 @@
 
     private final ArrayMap<Uri, BroadcastRelay> mRelays = new ArrayMap<>();
 
+    public SliceBroadcastRelayHandler(Context context) {
+        super(context);
+    }
+
     @Override
     public void start() {
         if (DEBUG) Log.d(TAG, "Start");
diff --git a/packages/SystemUI/src/com/android/systemui/SystemBars.java b/packages/SystemUI/src/com/android/systemui/SystemBars.java
deleted file mode 100644
index c4c0fd6..0000000
--- a/packages/SystemUI/src/com/android/systemui/SystemBars.java
+++ /dev/null
@@ -1,88 +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;
-
-import android.util.Log;
-
-import com.android.systemui.statusbar.phone.StatusBar;
-
-import java.io.FileDescriptor;
-import java.io.PrintWriter;
-
-/**
- * Ensure a single status bar service implementation is running at all times, using the in-process
- * implementation according to the product config.
- */
-public class SystemBars extends SystemUI {
-    private static final String TAG = "SystemBars";
-    private static final boolean DEBUG = false;
-    private static final int WAIT_FOR_BARS_TO_DIE = 500;
-
-    // in-process fallback implementation, per the product config
-    private SystemUI mStatusBar;
-
-    @Override
-    public void start() {
-        if (DEBUG) Log.d(TAG, "start");
-        createStatusBarFromConfig();
-    }
-
-    @Override
-    public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
-        if (mStatusBar != null) {
-            mStatusBar.dump(fd, pw, args);
-        }
-    }
-
-    @Override
-    public void onBootCompleted() {
-        if (mStatusBar != null) {
-            mStatusBar.onBootCompleted();
-        }
-    }
-
-    private void createStatusBarFromConfig() {
-        if (DEBUG) Log.d(TAG, "createStatusBarFromConfig");
-        final String clsName = mContext.getString(R.string.config_statusBarComponent);
-        if (clsName == null || clsName.length() == 0) {
-            throw andLog("No status bar component configured", null);
-        }
-        Class<?> cls = null;
-        try {
-            cls = mContext.getClassLoader().loadClass(clsName);
-        } catch (Throwable t) {
-            throw andLog("Error loading status bar component: " + clsName, t);
-        }
-        try {
-            mStatusBar = (SystemUI) cls.newInstance();
-        } catch (Throwable t) {
-            throw andLog("Error creating status bar component: " + clsName, t);
-        }
-        mStatusBar.mContext = mContext;
-        mStatusBar.mComponents = mComponents;
-        if (mStatusBar instanceof StatusBar) {
-            SystemUIFactory.getInstance().getRootComponent()
-                    .getStatusBarInjector()
-                    .createStatusBar((StatusBar) mStatusBar);
-        }
-        mStatusBar.start();
-        if (DEBUG) Log.d(TAG, "started " + mStatusBar.getClass().getSimpleName());
-    }
-
-    private RuntimeException andLog(String msg, Throwable t) {
-        Log.w(TAG, msg, t);
-        throw new RuntimeException(msg, t);
-    }
-}
diff --git a/packages/SystemUI/src/com/android/systemui/SystemUI.java b/packages/SystemUI/src/com/android/systemui/SystemUI.java
index 30fbef6..7570037 100644
--- a/packages/SystemUI/src/com/android/systemui/SystemUI.java
+++ b/packages/SystemUI/src/com/android/systemui/SystemUI.java
@@ -26,9 +26,13 @@
 import java.util.Map;
 
 public abstract class SystemUI implements SysUiServiceProvider {
-    public Context mContext;
+    protected final Context mContext;
     public Map<Class<?>, Object> mComponents;
 
+    public SystemUI(Context context) {
+        mContext = context;
+    }
+
     public abstract void start();
 
     protected void onConfigurationChanged(Configuration newConfig) {
diff --git a/packages/SystemUI/src/com/android/systemui/SystemUIApplication.java b/packages/SystemUI/src/com/android/systemui/SystemUIApplication.java
index 56b5d08..189e511 100644
--- a/packages/SystemUI/src/com/android/systemui/SystemUIApplication.java
+++ b/packages/SystemUI/src/com/android/systemui/SystemUIApplication.java
@@ -42,6 +42,8 @@
 import com.android.systemui.statusbar.phone.StatusBarWindowController;
 import com.android.systemui.util.NotificationChannels;
 
+import java.lang.reflect.Constructor;
+import java.lang.reflect.InvocationTargetException;
 import java.util.HashMap;
 import java.util.Map;
 
@@ -193,18 +195,18 @@
             try {
                 SystemUI obj = mComponentHelper.resolveSystemUI(clsName);
                 if (obj == null) {
-                    obj = (SystemUI) Class.forName(clsName).newInstance();
+                    Constructor constructor = Class.forName(clsName).getConstructor(Context.class);
+                    obj = (SystemUI) constructor.newInstance(this);
                 }
                 mServices[i] = obj;
-            } catch (ClassNotFoundException ex) {
-                throw new RuntimeException(ex);
-            } catch (IllegalAccessException ex) {
-                throw new RuntimeException(ex);
-            } catch (InstantiationException ex) {
+            } catch (ClassNotFoundException
+                    | NoSuchMethodException
+                    | IllegalAccessException
+                    | InstantiationException
+                    | InvocationTargetException ex) {
                 throw new RuntimeException(ex);
             }
 
-            mServices[i].mContext = this;
             mServices[i].mComponents = mComponents;
             if (DEBUG) Log.d(TAG, "running: " + mServices[i]);
             mServices[i].start();
diff --git a/packages/SystemUI/src/com/android/systemui/SystemUIBinder.java b/packages/SystemUI/src/com/android/systemui/SystemUIBinder.java
index ba2dec0..a5a5598 100644
--- a/packages/SystemUI/src/com/android/systemui/SystemUIBinder.java
+++ b/packages/SystemUI/src/com/android/systemui/SystemUIBinder.java
@@ -17,10 +17,12 @@
 package com.android.systemui;
 
 import com.android.systemui.keyguard.KeyguardViewMediator;
+import com.android.systemui.pip.PipUI;
 import com.android.systemui.power.PowerUI;
 import com.android.systemui.recents.Recents;
 import com.android.systemui.recents.RecentsModule;
 import com.android.systemui.util.leak.GarbageMonitor;
+import com.android.systemui.volume.VolumeUI;
 
 import dagger.Binds;
 import dagger.Module;
@@ -32,27 +34,41 @@
  */
 @Module(includes = {RecentsModule.class})
 public abstract class SystemUIBinder {
+
+    /** Inject into GarbageMonitor.Service. */
+    @Binds
+    @IntoMap
+    @ClassKey(GarbageMonitor.Service.class)
+    public abstract SystemUI bindGarbageMonitorService(GarbageMonitor.Service service);
+
     /** Inject into KeyguardViewMediator. */
     @Binds
     @IntoMap
     @ClassKey(KeyguardViewMediator.class)
     public abstract SystemUI bindKeyguardViewMediator(KeyguardViewMediator sysui);
 
+    /** Inject into PipUI. */
+    @Binds
+    @IntoMap
+    @ClassKey(PipUI.class)
+    public abstract SystemUI bindPipUI(PipUI sysui);
+
     /** Inject into PowerUI. */
     @Binds
     @IntoMap
     @ClassKey(PowerUI.class)
     public abstract SystemUI bindPowerUI(PowerUI sysui);
 
-    /** Inject into StatusBar. */
+    /** Inject into Recents. */
     @Binds
     @IntoMap
     @ClassKey(Recents.class)
     public abstract SystemUI bindRecents(Recents sysui);
 
-    /** Inject into GarbageMonitor.Service. */
+    /** Inject into VolumeUI. */
     @Binds
     @IntoMap
-    @ClassKey(GarbageMonitor.Service.class)
-    public abstract SystemUI bindGarbageMonitorService(GarbageMonitor.Service service);
+    @ClassKey(VolumeUI.class)
+    public abstract SystemUI bindVolumeUI(VolumeUI sysui);
+
 }
diff --git a/packages/SystemUI/src/com/android/systemui/SystemUIDefaultModule.java b/packages/SystemUI/src/com/android/systemui/SystemUIDefaultModule.java
index 262b5ec..176bcbf 100644
--- a/packages/SystemUI/src/com/android/systemui/SystemUIDefaultModule.java
+++ b/packages/SystemUI/src/com/android/systemui/SystemUIDefaultModule.java
@@ -19,8 +19,6 @@
 import static com.android.systemui.Dependency.ALLOW_NOTIFICATION_LONG_PRESS_NAME;
 import static com.android.systemui.Dependency.LEAK_REPORT_EMAIL_NAME;
 
-import android.content.Context;
-
 import androidx.annotation.Nullable;
 
 import com.android.systemui.dock.DockManager;
@@ -40,6 +38,8 @@
 import dagger.Binds;
 import dagger.Module;
 import dagger.Provides;
+import dagger.multibindings.ClassKey;
+import dagger.multibindings.IntoMap;
 
 /**
  * A dagger module for injecting default implementations of components of System UI that may be
@@ -70,11 +70,13 @@
     abstract NotificationData.KeyguardEnvironment bindKeyguardEnvironment(
             KeyguardEnvironmentImpl keyguardEnvironment);
 
-    @Singleton
-    @Provides
-    static ShadeController provideShadeController(Context context) {
-        return SysUiServiceProvider.getComponent(context, StatusBar.class);
-    }
+    @Binds
+    abstract ShadeController provideShadeController(StatusBar statusBar);
+
+    @Binds
+    @IntoMap
+    @ClassKey(StatusBar.class)
+    public abstract SystemUI providesStatusBar(StatusBar statusBar);
 
     @Singleton
     @Provides
diff --git a/packages/SystemUI/src/com/android/systemui/SystemUIFactory.java b/packages/SystemUI/src/com/android/systemui/SystemUIFactory.java
index 530dcdc..da4f304 100644
--- a/packages/SystemUI/src/com/android/systemui/SystemUIFactory.java
+++ b/packages/SystemUI/src/com/android/systemui/SystemUIFactory.java
@@ -48,7 +48,6 @@
 import com.android.systemui.statusbar.phone.StatusBar;
 import com.android.systemui.statusbar.phone.StatusBarKeyguardViewManager;
 import com.android.systemui.statusbar.policy.KeyguardStateController;
-import com.android.systemui.volume.VolumeDialogComponent;
 
 import java.util.function.Consumer;
 
@@ -169,10 +168,6 @@
         return new KeyguardIndicationController(context, indicationArea, lockIcon);
     }
 
-    public VolumeDialogComponent createVolumeDialogComponent(SystemUI systemUi, Context context) {
-        return new VolumeDialogComponent(systemUi, context);
-    }
-
     @Module
     public static class ContextHolder {
         private Context mContext;
diff --git a/packages/SystemUI/src/com/android/systemui/VendorServices.java b/packages/SystemUI/src/com/android/systemui/VendorServices.java
index 0be6b12..13d847b 100644
--- a/packages/SystemUI/src/com/android/systemui/VendorServices.java
+++ b/packages/SystemUI/src/com/android/systemui/VendorServices.java
@@ -16,11 +16,17 @@
 
 package com.android.systemui;
 
+import android.content.Context;
+
 /**
  * Placeholder for any vendor-specific services.
  */
 public class VendorServices extends SystemUI {
 
+    public VendorServices(Context context) {
+        super(context);
+    }
+
     @Override
     public void start() {
         // no-op
diff --git a/packages/SystemUI/src/com/android/systemui/assist/AssistHandleViewController.java b/packages/SystemUI/src/com/android/systemui/assist/AssistHandleViewController.java
index f9ffb80..5010f31 100644
--- a/packages/SystemUI/src/com/android/systemui/assist/AssistHandleViewController.java
+++ b/packages/SystemUI/src/com/android/systemui/assist/AssistHandleViewController.java
@@ -43,6 +43,7 @@
     private Handler mHandler;
     private CornerHandleView mAssistHintLeft;
     private CornerHandleView mAssistHintRight;
+    private int mBottomOffset;
 
     @VisibleForTesting
     boolean mAssistHintVisible;
@@ -62,6 +63,23 @@
     }
 
     /**
+     * Set the bottom offset.
+     *
+     * @param bottomOffset the bottom offset to translate.
+     */
+    public void setBottomOffset(int bottomOffset) {
+        if (mBottomOffset != bottomOffset) {
+            mBottomOffset = bottomOffset;
+            if (mAssistHintVisible) {
+                // If assist handles are visible, hide them without animation and then make them
+                // show once again (with corrected bottom offset).
+                hideAssistHandles();
+                setAssistHintVisible(true);
+            }
+        }
+    }
+
+    /**
      * Controls the visibility of the assist gesture handles.
      *
      * @param visible whether the handles should be shown
@@ -126,7 +144,8 @@
                 xDirection * translationStart * view.getWidth(),
                 xDirection * translationEnd * view.getWidth());
         Animator translateY = ObjectAnimator.ofFloat(view, View.TRANSLATION_Y,
-                translationStart * view.getHeight(), translationEnd * view.getHeight());
+                translationStart * view.getHeight() + mBottomOffset,
+                translationEnd * view.getHeight() + mBottomOffset);
 
         AnimatorSet set = new AnimatorSet();
         set.play(scaleX).with(scaleY);
diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/AuthBiometricView.java b/packages/SystemUI/src/com/android/systemui/biometrics/AuthBiometricView.java
index 73bbce9..d20cd72 100644
--- a/packages/SystemUI/src/com/android/systemui/biometrics/AuthBiometricView.java
+++ b/packages/SystemUI/src/com/android/systemui/biometrics/AuthBiometricView.java
@@ -16,8 +16,6 @@
 
 package com.android.systemui.biometrics;
 
-import static android.view.accessibility.AccessibilityEvent.CONTENT_CHANGE_TYPE_SUBTREE;
-
 import android.animation.Animator;
 import android.animation.AnimatorListenerAdapter;
 import android.animation.AnimatorSet;
@@ -25,6 +23,7 @@
 import android.annotation.IntDef;
 import android.annotation.NonNull;
 import android.annotation.Nullable;
+import android.app.admin.DevicePolicyManager;
 import android.content.Context;
 import android.hardware.biometrics.BiometricPrompt;
 import android.os.Bundle;
@@ -34,7 +33,7 @@
 import android.util.AttributeSet;
 import android.util.Log;
 import android.view.View;
-import android.view.accessibility.AccessibilityEvent;
+import android.view.ViewGroup;
 import android.view.accessibility.AccessibilityManager;
 import android.widget.Button;
 import android.widget.ImageView;
@@ -42,10 +41,13 @@
 import android.widget.TextView;
 
 import com.android.internal.annotations.VisibleForTesting;
+import com.android.internal.widget.LockPatternUtils;
 import com.android.systemui.R;
 
 import java.lang.annotation.Retention;
 import java.lang.annotation.RetentionPolicy;
+import java.util.ArrayList;
+import java.util.List;
 
 /**
  * Contains the Biometric views (title, subtitle, icon, buttons, etc) and its controllers.
@@ -97,6 +99,7 @@
         int ACTION_BUTTON_NEGATIVE = 3;
         int ACTION_BUTTON_TRY_AGAIN = 4;
         int ACTION_ERROR = 5;
+        int ACTION_USE_DEVICE_CREDENTIAL = 6;
 
         /**
          * When an action has occurred. The caller will only invoke this when the callback should
@@ -145,6 +148,14 @@
         public int getDelayAfterError() {
             return BiometricPrompt.HIDE_DIALOG_DELAY;
         }
+
+        public int getMediumToLargeAnimationDurationMs() {
+            return AuthDialog.ANIMATE_MEDIUM_TO_LARGE_DURATION_MS;
+        }
+
+        public int getAnimateCredentialStartDelayMs() {
+            return AuthDialog.ANIMATE_CREDENTIAL_START_DELAY_MS;
+        }
     }
 
     private final Injector mInjector;
@@ -154,8 +165,9 @@
     private final int mTextColorHint;
 
     private AuthPanelController mPanelController;
-    private Bundle mBundle;
+    private Bundle mBiometricPromptBundle;
     private boolean mRequireConfirmation;
+    private int mUserId;
     @AuthDialog.DialogSize int mSize = AuthDialog.SIZE_UNKNOWN;
 
     private TextView mTitleView;
@@ -212,6 +224,9 @@
         } else if (mSize == AuthDialog.SIZE_SMALL) {
             Log.w(TAG, "Ignoring background click during small dialog");
             return;
+        } else if (mSize == AuthDialog.SIZE_LARGE) {
+            Log.w(TAG, "Ignoring background click during large dialog");
+            return;
         }
         mCallback.onAction(Callback.ACTION_USER_CANCELED);
     };
@@ -256,7 +271,7 @@
     }
 
     public void setBiometricPromptBundle(Bundle bundle) {
-        mBundle = bundle;
+        mBiometricPromptBundle = bundle;
     }
 
     public void setCallback(Callback callback) {
@@ -267,6 +282,10 @@
         backgroundView.setOnClickListener(mBackgroundClickListener);
     }
 
+    public void setUserId(int userId) {
+        mUserId = userId;
+    }
+
     public void setRequireConfirmation(boolean requireConfirmation) {
         mRequireConfirmation = requireConfirmation;
     }
@@ -287,7 +306,7 @@
 
             final int newHeight = mIconView.getHeight() + 2 * (int) iconPadding;
             mPanelController.updateForContentDimensions(mMediumWidth, newHeight,
-                    false /* animate */);
+                    0 /* animateDurationMs */);
 
             mSize = newSize;
         } else if (mSize == AuthDialog.SIZE_SMALL && newSize == AuthDialog.SIZE_MEDIUM) {
@@ -305,10 +324,8 @@
 
             // Animate the text
             final ValueAnimator opacityAnimator = ValueAnimator.ofFloat(0, 1);
-            opacityAnimator.setDuration(AuthDialog.ANIMATE_DURATION_MS);
             opacityAnimator.addUpdateListener((animation) -> {
                 final float opacity = (float) animation.getAnimatedValue();
-
                 mTitleView.setAlpha(opacity);
                 mIndicatorView.setAlpha(opacity);
                 mNegativeButton.setAlpha(opacity);
@@ -324,7 +341,7 @@
 
             // Choreograph together
             final AnimatorSet as = new AnimatorSet();
-            as.setDuration(AuthDialog.ANIMATE_DURATION_MS);
+            as.setDuration(AuthDialog.ANIMATE_SMALL_TO_MEDIUM_DURATION_MS);
             as.addListener(new AnimatorListenerAdapter() {
                 @Override
                 public void onAnimationStart(Animator animation) {
@@ -355,11 +372,73 @@
             as.start();
             // Animate the panel
             mPanelController.updateForContentDimensions(mMediumWidth, mMediumHeight,
-                    true /* animate */);
+                    AuthDialog.ANIMATE_SMALL_TO_MEDIUM_DURATION_MS);
         } else if (newSize == AuthDialog.SIZE_MEDIUM) {
             mPanelController.updateForContentDimensions(mMediumWidth, mMediumHeight,
-                    false /* animate */);
+                    0 /* animateDurationMs */);
             mSize = newSize;
+        } else if (newSize == AuthDialog.SIZE_LARGE) {
+            final boolean isManagedProfile = Utils.isManagedProfile(mContext, mUserId);
+
+            // If it's a managed profile, animate the contents and panel down, since the credential
+            // contents will be shown on the same "layer" as the background. If it's not a managed
+            // profile, animate the contents up and expand the panel to full-screen - the credential
+            // contents will be shown on the same "layer" as the panel.
+            final float translationY = isManagedProfile ?
+                    -getResources().getDimension(
+                            R.dimen.biometric_dialog_animation_translation_offset)
+                    : getResources().getDimension(
+                            R.dimen.biometric_dialog_medium_to_large_translation_offset);
+            final AuthBiometricView biometricView = this;
+
+            // Translate at full duration
+            final ValueAnimator translationAnimator = ValueAnimator.ofFloat(
+                    biometricView.getY(), biometricView.getY() - translationY);
+            translationAnimator.setDuration(mInjector.getMediumToLargeAnimationDurationMs());
+            translationAnimator.addUpdateListener((animation) -> {
+                final float translation = (float) animation.getAnimatedValue();
+                biometricView.setTranslationY(translation);
+            });
+            translationAnimator.addListener(new AnimatorListenerAdapter() {
+                @Override
+                public void onAnimationEnd(Animator animation) {
+                    super.onAnimationEnd(animation);
+                    if (biometricView.getParent() != null) {
+                        ((ViewGroup) biometricView.getParent()).removeView(biometricView);
+                    }
+                    mSize = newSize;
+                }
+            });
+
+            // Opacity to 0 in half duration
+            final ValueAnimator opacityAnimator = ValueAnimator.ofFloat(1, 0);
+            opacityAnimator.setDuration(mInjector.getMediumToLargeAnimationDurationMs() / 2);
+            opacityAnimator.addUpdateListener((animation) -> {
+                final float opacity = (float) animation.getAnimatedValue();
+                biometricView.setAlpha(opacity);
+            });
+
+            if (!isManagedProfile) {
+                mPanelController.setUseFullScreen(true);
+                mPanelController.updateForContentDimensions(
+                        mPanelController.getContainerWidth(),
+                        mPanelController.getContainerHeight(),
+                        mInjector.getMediumToLargeAnimationDurationMs());
+            }
+
+            // Start the animations together
+            AnimatorSet as = new AnimatorSet();
+            List<Animator> animators = new ArrayList<>();
+            animators.add(translationAnimator);
+            animators.add(opacityAnimator);
+            if (isManagedProfile) {
+                animators.add(mPanelController.getTranslationAnimator(translationY));
+                animators.add(mPanelController.getAlphaAnimator(0));
+            }
+            as.playTogether(animators);
+            as.setDuration(isManagedProfile ? mInjector.getMediumToLargeAnimationDurationMs()
+                    : mInjector.getMediumToLargeAnimationDurationMs() * 2 / 3);
+            as.start();
         } else {
             Log.e(TAG, "Unknown transition from: " + mSize + " to: " + newSize);
         }
@@ -528,7 +607,11 @@
             if (mState == STATE_PENDING_CONFIRMATION) {
                 mCallback.onAction(Callback.ACTION_USER_CANCELED);
             } else {
-                mCallback.onAction(Callback.ACTION_BUTTON_NEGATIVE);
+                if (isDeviceCredentialAllowed()) {
+                    startTransitionToCredentialUI();
+                } else {
+                    mCallback.onAction(Callback.ACTION_BUTTON_NEGATIVE);
+                }
             }
         });
 
@@ -544,6 +627,16 @@
         });
     }
 
+    /**
+     * Kicks off the animation process and invokes the callback.
+     */
+    void startTransitionToCredentialUI() {
+        updateSize(AuthDialog.SIZE_LARGE);
+        mHandler.postDelayed(() -> {
+            mCallback.onAction(Callback.ACTION_USE_DEVICE_CREDENTIAL);
+        }, mInjector.getAnimateCredentialStartDelayMs());
+    }
+
     @Override
     protected void onAttachedToWindow() {
         super.onAttachedToWindow();
@@ -556,11 +649,37 @@
      */
     @VisibleForTesting
     void onAttachedToWindowInternal() {
-        setText(mTitleView, mBundle.getString(BiometricPrompt.KEY_TITLE));
-        setText(mNegativeButton, mBundle.getString(BiometricPrompt.KEY_NEGATIVE_TEXT));
+        setText(mTitleView, mBiometricPromptBundle.getString(BiometricPrompt.KEY_TITLE));
 
-        setTextOrHide(mSubtitleView, mBundle.getString(BiometricPrompt.KEY_SUBTITLE));
-        setTextOrHide(mDescriptionView, mBundle.getString(BiometricPrompt.KEY_DESCRIPTION));
+        final String negativeText;
+        if (isDeviceCredentialAllowed()) {
+
+            final @Utils.CredentialType int credentialType =
+                    Utils.getCredentialType(mContext, mUserId);
+            switch(credentialType) {
+                case Utils.CREDENTIAL_PIN:
+                    negativeText = getResources().getString(R.string.biometric_dialog_use_pin);
+                    break;
+                case Utils.CREDENTIAL_PATTERN:
+                    negativeText = getResources().getString(R.string.biometric_dialog_use_pattern);
+                    break;
+                case Utils.CREDENTIAL_PASSWORD:
+                    negativeText = getResources().getString(R.string.biometric_dialog_use_password);
+                    break;
+                default:
+                    negativeText = getResources().getString(R.string.biometric_dialog_use_password);
+                    break;
+            }
+
+        } else {
+            negativeText = mBiometricPromptBundle.getString(BiometricPrompt.KEY_NEGATIVE_TEXT);
+        }
+        setText(mNegativeButton, negativeText);
+
+        setTextOrHide(mSubtitleView,
+                mBiometricPromptBundle.getString(BiometricPrompt.KEY_SUBTITLE));
+        setTextOrHide(mDescriptionView,
+                mBiometricPromptBundle.getString(BiometricPrompt.KEY_DESCRIPTION));
 
         if (mSavedState == null) {
             updateState(STATE_AUTHENTICATING_ANIMATING_IN);
@@ -655,4 +774,8 @@
             }
         }
     }
+
+    private boolean isDeviceCredentialAllowed() {
+        return Utils.isDeviceCredentialAllowed(mBiometricPromptBundle);
+    }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/AuthContainerView.java b/packages/SystemUI/src/com/android/systemui/biometrics/AuthContainerView.java
index 6555c75..a9359d4 100644
--- a/packages/SystemUI/src/com/android/systemui/biometrics/AuthContainerView.java
+++ b/packages/SystemUI/src/com/android/systemui/biometrics/AuthContainerView.java
@@ -24,7 +24,9 @@
 import android.graphics.PixelFormat;
 import android.graphics.PorterDuff;
 import android.graphics.drawable.Drawable;
+import android.hardware.biometrics.Authenticator;
 import android.hardware.biometrics.BiometricAuthenticator;
+import android.hardware.biometrics.BiometricPrompt;
 import android.os.Binder;
 import android.os.Bundle;
 import android.os.IBinder;
@@ -36,6 +38,7 @@
 import android.view.ViewGroup;
 import android.view.WindowManager;
 import android.view.animation.Interpolator;
+import android.widget.FrameLayout;
 import android.widget.ImageView;
 import android.widget.LinearLayout;
 import android.widget.ScrollView;
@@ -72,17 +75,20 @@
     @interface ContainerState {}
 
     final Config mConfig;
+    private final Injector mInjector;
     private final IBinder mWindowToken = new Binder();
     private final WindowManager mWindowManager;
     private final AuthPanelController mPanelController;
     private final Interpolator mLinearOutSlowIn;
     @VisibleForTesting final BiometricCallback mBiometricCallback;
+    private final CredentialCallback mCredentialCallback;
 
-    private final ViewGroup mContainerView;
-    private final AuthBiometricView mBiometricView;
+    @VisibleForTesting final FrameLayout mFrameLayout;
+    @VisibleForTesting @Nullable AuthBiometricView mBiometricView;
+    @VisibleForTesting @Nullable AuthCredentialView mCredentialView;
 
     private final ImageView mBackgroundView;
-    private final ScrollView mScrollView;
+    @VisibleForTesting final ScrollView mBiometricScrollView;
     private final View mPanelView;
 
     private final float mTranslationY;
@@ -145,7 +151,31 @@
 
         public AuthContainerView build(int modalityMask) {
             mConfig.mModalityMask = modalityMask;
-            return new AuthContainerView(mConfig);
+            return new AuthContainerView(mConfig, new Injector());
+        }
+    }
+
+    public static class Injector {
+        ScrollView getBiometricScrollView(FrameLayout parent) {
+            return parent.findViewById(R.id.biometric_scrollview);
+        }
+
+        FrameLayout inflateContainerView(LayoutInflater factory, ViewGroup root) {
+            return (FrameLayout) factory.inflate(
+                    R.layout.auth_container_view, root, false /* attachToRoot */);
+        }
+
+        AuthPanelController getPanelController(Context context, View panelView,
+                boolean isManagedProfile) {
+            return new AuthPanelController(context, panelView, isManagedProfile);
+        }
+
+        ImageView getBackgroundView(FrameLayout parent) {
+            return parent.findViewById(R.id.background);
+        }
+
+        View getPanelView(FrameLayout parent) {
+            return parent.findViewById(R.id.panel);
         }
     }
 
@@ -155,7 +185,7 @@
         public void onAction(int action) {
             switch (action) {
                 case AuthBiometricView.Callback.ACTION_AUTHENTICATED:
-                    animateAway(AuthDialogCallback.DISMISSED_AUTHENTICATED);
+                    animateAway(AuthDialogCallback.DISMISSED_BIOMETRIC_AUTHENTICATED);
                     break;
                 case AuthBiometricView.Callback.ACTION_USER_CANCELED:
                     animateAway(AuthDialogCallback.DISMISSED_USER_CANCELED);
@@ -169,17 +199,30 @@
                 case AuthBiometricView.Callback.ACTION_ERROR:
                     animateAway(AuthDialogCallback.DISMISSED_ERROR);
                     break;
+                case AuthBiometricView.Callback.ACTION_USE_DEVICE_CREDENTIAL:
+                    mConfig.mCallback.onDeviceCredentialPressed();
+                    addCredentialView(false /* animatePanel */, true /* animateContents */);
+                    break;
                 default:
                     Log.e(TAG, "Unhandled action: " + action);
             }
         }
     }
 
+    final class CredentialCallback implements AuthCredentialView.Callback {
+        @Override
+        public void onCredentialMatched() {
+            animateAway(AuthDialogCallback.DISMISSED_CREDENTIAL_AUTHENTICATED);
+        }
+    }
+
     @VisibleForTesting
-    AuthContainerView(Config config) {
+    AuthContainerView(Config config, Injector injector) {
         super(config.mContext);
 
         mConfig = config;
+        mInjector = injector;
+
         mWindowManager = mContext.getSystemService(WindowManager.class);
         mWakefulnessLifecycle = Dependency.get(WakefulnessLifecycle.class);
 
@@ -187,51 +230,48 @@
                 .getDimension(R.dimen.biometric_dialog_animation_translation_offset);
         mLinearOutSlowIn = Interpolators.LINEAR_OUT_SLOW_IN;
         mBiometricCallback = new BiometricCallback();
+        mCredentialCallback = new CredentialCallback();
 
         final LayoutInflater factory = LayoutInflater.from(mContext);
-        mContainerView = (ViewGroup) factory.inflate(
-                R.layout.auth_container_view, this, false /* attachToRoot */);
+        mFrameLayout = mInjector.inflateContainerView(factory, this);
 
-        mPanelView = mContainerView.findViewById(R.id.panel);
-        mPanelController = new AuthPanelController(mContext, mPanelView);
+        final boolean isManagedProfile = Utils.isManagedProfile(mContext, mConfig.mUserId);
 
-        // TODO: Update with new controllers if multi-modal authentication can occur simultaneously
-        if (config.mModalityMask == BiometricAuthenticator.TYPE_FINGERPRINT) {
-            mBiometricView = (AuthBiometricFingerprintView)
-                    factory.inflate(R.layout.auth_biometric_fingerprint_view, null, false);
-        } else if (config.mModalityMask == BiometricAuthenticator.TYPE_FACE) {
-            mBiometricView = (AuthBiometricFaceView)
-                    factory.inflate(R.layout.auth_biometric_face_view, null, false);
-        } else {
-            Log.e(TAG, "Unsupported modality mask: " + config.mModalityMask);
-            mBiometricView = null;
-            mBackgroundView = null;
-            mScrollView = null;
-            return;
+        mPanelView = mInjector.getPanelView(mFrameLayout);
+        mPanelController = mInjector.getPanelController(mContext, mPanelView, isManagedProfile);
+
+        // Inflate biometric view only if necessary.
+        if (Utils.isBiometricAllowed(mConfig.mBiometricPromptBundle)) {
+            if (config.mModalityMask == BiometricAuthenticator.TYPE_FINGERPRINT) {
+                mBiometricView = (AuthBiometricFingerprintView)
+                        factory.inflate(R.layout.auth_biometric_fingerprint_view, null, false);
+            } else if (config.mModalityMask == BiometricAuthenticator.TYPE_FACE) {
+                mBiometricView = (AuthBiometricFaceView)
+                        factory.inflate(R.layout.auth_biometric_face_view, null, false);
+            } else {
+                Log.e(TAG, "Unsupported biometric modality: " + config.mModalityMask);
+                mBiometricView = null;
+                mBackgroundView = null;
+                mBiometricScrollView = null;
+                return;
+            }
         }
 
-        mBackgroundView = mContainerView.findViewById(R.id.background);
+        mBiometricScrollView = mInjector.getBiometricScrollView(mFrameLayout);
+        mBackgroundView = mInjector.getBackgroundView(mFrameLayout);
 
-        UserManager userManager = mContext.getSystemService(UserManager.class);
-        DevicePolicyManager dpm = mContext.getSystemService(DevicePolicyManager.class);
-        if (userManager.isManagedProfile(mConfig.mUserId)) {
+
+        if (isManagedProfile) {
             final Drawable image = getResources().getDrawable(R.drawable.work_challenge_background,
                     mContext.getTheme());
+            final DevicePolicyManager dpm = mContext.getSystemService(DevicePolicyManager.class);
             image.setColorFilter(dpm.getOrganizationColorForUser(mConfig.mUserId),
                     PorterDuff.Mode.DARKEN);
             mBackgroundView.setScaleType(ImageView.ScaleType.CENTER_CROP);
             mBackgroundView.setImageDrawable(image);
         }
 
-        mBiometricView.setRequireConfirmation(mConfig.mRequireConfirmation);
-        mBiometricView.setPanelController(mPanelController);
-        mBiometricView.setBiometricPromptBundle(config.mBiometricPromptBundle);
-        mBiometricView.setCallback(mBiometricCallback);
-        mBiometricView.setBackgroundView(mBackgroundView);
-
-        mScrollView = mContainerView.findViewById(R.id.scrollview);
-        mScrollView.addView(mBiometricView);
-        addView(mContainerView);
+        addView(mFrameLayout);
 
         setOnKeyListener((v, keyCode, event) -> {
             if (keyCode != KeyEvent.KEYCODE_BACK) {
@@ -248,6 +288,53 @@
     }
 
     @Override
+    public boolean isAllowDeviceCredentials() {
+        return Utils.isDeviceCredentialAllowed(mConfig.mBiometricPromptBundle);
+    }
+
+    private void addBiometricView() {
+        mBiometricView.setRequireConfirmation(mConfig.mRequireConfirmation);
+        mBiometricView.setPanelController(mPanelController);
+        mBiometricView.setBiometricPromptBundle(mConfig.mBiometricPromptBundle);
+        mBiometricView.setCallback(mBiometricCallback);
+        mBiometricView.setBackgroundView(mBackgroundView);
+        mBiometricView.setUserId(mConfig.mUserId);
+        mBiometricScrollView.addView(mBiometricView);
+    }
+
+    /**
+     * Adds the credential view. When going from biometric to credential view, the biometric
+     * view starts the panel expansion animation. If the credential view is being shown first,
+     * it should own the panel expansion.
+     * @param animatePanel if the credential view needs to own the panel expansion animation
+     */
+    private void addCredentialView(boolean animatePanel, boolean animateContents) {
+        final LayoutInflater factory = LayoutInflater.from(mContext);
+        final int credentialType = Utils.getCredentialType(mContext, mConfig.mUserId);
+        switch (credentialType) {
+            case Utils.CREDENTIAL_PATTERN:
+                mCredentialView = (AuthCredentialView) factory.inflate(
+                        R.layout.auth_credential_pattern_view, null, false);
+                break;
+            case Utils.CREDENTIAL_PIN:
+            case Utils.CREDENTIAL_PASSWORD:
+                mCredentialView = (AuthCredentialView) factory.inflate(
+                        R.layout.auth_credential_password_view, null, false);
+                break;
+            default:
+                throw new IllegalStateException("Unknown credential type: " + credentialType);
+        }
+
+        mCredentialView.setContainerView(this);
+        mCredentialView.setUser(mConfig.mUserId);
+        mCredentialView.setCallback(mCredentialCallback);
+        mCredentialView.setBiometricPromptBundle(mConfig.mBiometricPromptBundle);
+        mCredentialView.setPanelController(mPanelController, animatePanel);
+        mCredentialView.setShouldAnimateContents(animateContents);
+        mFrameLayout.addView(mCredentialView);
+    }
+
+    @Override
     protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
         super.onMeasure(widthMeasureSpec, heightMeasureSpec);
         mPanelController.setContainerDimensions(getMeasuredWidth(), getMeasuredHeight());
@@ -256,8 +343,22 @@
     @Override
     public void onAttachedToWindow() {
         super.onAttachedToWindow();
+        onAttachedToWindowInternal();
+    }
+
+    @VisibleForTesting
+    void onAttachedToWindowInternal() {
         mWakefulnessLifecycle.addObserver(this);
 
+        if (Utils.isBiometricAllowed(mConfig.mBiometricPromptBundle)) {
+            addBiometricView();
+        } else if (Utils.isDeviceCredentialAllowed(mConfig.mBiometricPromptBundle)) {
+            addCredentialView(true /* animatePanel */, false /* animateContents */);
+        } else {
+            throw new IllegalStateException("Unknown configuration: "
+                    + Utils.getAuthenticators(mConfig.mBiometricPromptBundle));
+        }
+
         if (mConfig.mSkipIntro) {
             mContainerState = STATE_SHOWING;
         } else {
@@ -265,7 +366,7 @@
             // The background panel and content are different views since we need to be able to
             // animate them separately in other places.
             mPanelView.setY(mTranslationY);
-            mScrollView.setY(mTranslationY);
+            mBiometricScrollView.setY(mTranslationY);
 
             setAlpha(0f);
             postOnAnimation(() -> {
@@ -276,12 +377,21 @@
                         .withLayer()
                         .withEndAction(this::onDialogAnimatedIn)
                         .start();
-                mScrollView.animate()
+                mBiometricScrollView.animate()
                         .translationY(0)
                         .setDuration(ANIMATION_DURATION_SHOW_MS)
                         .setInterpolator(mLinearOutSlowIn)
                         .withLayer()
                         .start();
+                if (mCredentialView != null && mCredentialView.isAttachedToWindow()) {
+                    mCredentialView.setY(mTranslationY);
+                    mCredentialView.animate()
+                            .translationY(0)
+                            .setDuration(ANIMATION_DURATION_SHOW_MS)
+                            .setInterpolator(mLinearOutSlowIn)
+                            .withLayer()
+                            .start();
+                }
                 animate()
                         .alpha(1f)
                         .setDuration(ANIMATION_DURATION_SHOW_MS)
@@ -305,7 +415,9 @@
 
     @Override
     public void show(WindowManager wm, @Nullable Bundle savedState) {
-        mBiometricView.restoreState(savedState);
+        if (mBiometricView != null) {
+            mBiometricView.restoreState(savedState);
+        }
         wm.addView(this, getLayoutParams(mWindowToken));
     }
 
@@ -346,7 +458,15 @@
     @Override
     public void onSaveState(@NonNull Bundle outState) {
         outState.putInt(AuthDialog.KEY_CONTAINER_STATE, mContainerState);
-        mBiometricView.onSaveState(outState);
+        // In the case where biometric and credential are both allowed, we can assume that
+        // biometric isn't showing if credential is showing since biometric is shown first.
+        outState.putBoolean(AuthDialog.KEY_BIOMETRIC_SHOWING,
+                mBiometricView != null && mCredentialView == null);
+        outState.putBoolean(AuthDialog.KEY_CREDENTIAL_SHOWING, mCredentialView != null);
+
+        if (mBiometricView != null) {
+            mBiometricView.onSaveState(outState);
+        }
     }
 
     @Override
@@ -354,6 +474,11 @@
         return mConfig.mOpPackageName;
     }
 
+    @Override
+    public void animateToCredentialUI() {
+        mBiometricView.startTransitionToCredentialUI();
+    }
+
     @VisibleForTesting
     void animateAway(int reason) {
         animateAway(true /* sendReason */, reason);
@@ -391,12 +516,20 @@
                     .withLayer()
                     .withEndAction(endActionRunnable)
                     .start();
-            mScrollView.animate()
+            mBiometricScrollView.animate()
                     .translationY(mTranslationY)
                     .setDuration(ANIMATION_DURATION_AWAY_MS)
                     .setInterpolator(mLinearOutSlowIn)
                     .withLayer()
                     .start();
+            if (mCredentialView != null && mCredentialView.isAttachedToWindow()) {
+                mCredentialView.animate()
+                        .translationY(mTranslationY)
+                        .setDuration(ANIMATION_DURATION_AWAY_MS)
+                        .setInterpolator(mLinearOutSlowIn)
+                        .withLayer()
+                        .start();
+            }
             animate()
                     .alpha(0f)
                     .setDuration(ANIMATION_DURATION_AWAY_MS)
@@ -431,7 +564,9 @@
             return;
         }
         mContainerState = STATE_SHOWING;
-        mBiometricView.onDialogAnimatedIn();
+        if (mBiometricView != null) {
+            mBiometricView.onDialogAnimatedIn();
+        }
     }
 
     /**
diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/AuthController.java b/packages/SystemUI/src/com/android/systemui/biometrics/AuthController.java
index d10a3fe..cdc2623 100644
--- a/packages/SystemUI/src/com/android/systemui/biometrics/AuthController.java
+++ b/packages/SystemUI/src/com/android/systemui/biometrics/AuthController.java
@@ -23,6 +23,8 @@
 import android.content.Context;
 import android.content.pm.PackageManager;
 import android.content.res.Configuration;
+import android.hardware.biometrics.Authenticator;
+import android.hardware.biometrics.BiometricConstants;
 import android.hardware.biometrics.BiometricPrompt;
 import android.hardware.biometrics.IBiometricServiceReceiverInternal;
 import android.os.Bundle;
@@ -105,6 +107,15 @@
     }
 
     @Override
+    public void onDeviceCredentialPressed() {
+        try {
+            mReceiver.onDeviceCredentialPressed();
+        } catch (RemoteException e) {
+            Log.e(TAG, "RemoteException when handling credential button", e);
+        }
+    }
+
+    @Override
     public void onDismissed(@DismissedReason int reason) {
         switch (reason) {
             case AuthDialogCallback.DISMISSED_USER_CANCELED:
@@ -116,11 +127,12 @@
                 break;
 
             case AuthDialogCallback.DISMISSED_BUTTON_POSITIVE:
-                sendResultAndCleanUp(BiometricPrompt.DISMISSED_REASON_CONFIRMED);
+                sendResultAndCleanUp(BiometricPrompt.DISMISSED_REASON_BIOMETRIC_CONFIRMED);
                 break;
 
-            case AuthDialogCallback.DISMISSED_AUTHENTICATED:
-                sendResultAndCleanUp(BiometricPrompt.DISMISSED_REASON_CONFIRM_NOT_REQUIRED);
+            case AuthDialogCallback.DISMISSED_BIOMETRIC_AUTHENTICATED:
+                sendResultAndCleanUp(
+                        BiometricPrompt.DISMISSED_REASON_BIOMETRIC_CONFIRM_NOT_REQUIRED);
                 break;
 
             case AuthDialogCallback.DISMISSED_ERROR:
@@ -131,6 +143,10 @@
                 sendResultAndCleanUp(BiometricPrompt.DISMISSED_REASON_SERVER_REQUESTED);
                 break;
 
+            case AuthDialogCallback.DISMISSED_CREDENTIAL_AUTHENTICATED:
+                sendResultAndCleanUp(BiometricPrompt.DISMISSED_REASON_CREDENTIAL_CONFIRMED);
+                break;
+
             default:
                 Log.e(TAG, "Unhandled reason: " + reason);
                 break;
@@ -156,12 +172,13 @@
         }
     }
 
-    public AuthController() {
-        this(new Injector());
+    public AuthController(Context context) {
+        this(context, new Injector());
     }
 
     @VisibleForTesting
-    AuthController(Injector injector) {
+    AuthController(Context context, Injector injector) {
+        super(context);
         mInjector = injector;
     }
 
@@ -185,16 +202,19 @@
     }
 
     @Override
-    public void showBiometricDialog(Bundle bundle, IBiometricServiceReceiverInternal receiver,
-            int type, boolean requireConfirmation, int userId, String opPackageName) {
+    public void showAuthenticationDialog(Bundle bundle, IBiometricServiceReceiverInternal receiver,
+            int biometricModality, boolean requireConfirmation, int userId, String opPackageName) {
+        final int authenticators = Utils.getAuthenticators(bundle);
+
         if (DEBUG) {
-            Log.d(TAG, "showBiometricDialog, type: " + type
+            Log.d(TAG, "showAuthenticationDialog, authenticators: " + authenticators
+                    + ", biometricModality: " + biometricModality
                     + ", requireConfirmation: " + requireConfirmation);
         }
         SomeArgs args = SomeArgs.obtain();
         args.arg1 = bundle;
         args.arg2 = receiver;
-        args.argi1 = type;
+        args.argi1 = biometricModality;
         args.arg3 = requireConfirmation;
         args.argi2 = userId;
         args.arg4 = opPackageName;
@@ -204,6 +224,7 @@
             Log.w(TAG, "mCurrentDialog: " + mCurrentDialog);
             skipAnimation = true;
         }
+
         showDialog(args, skipAnimation, null /* savedState */);
     }
 
@@ -227,14 +248,21 @@
     }
 
     @Override
-    public void onBiometricError(String error) {
-        if (DEBUG) Log.d(TAG, "onBiometricError: " + error);
-        mCurrentDialog.onError(error);
+    public void onBiometricError(int errorCode, String error) {
+        if (DEBUG) Log.d(TAG, "onBiometricError: " + errorCode + ", " + error);
+
+        final boolean isLockout = errorCode == BiometricConstants.BIOMETRIC_ERROR_LOCKOUT
+                || errorCode == BiometricConstants.BIOMETRIC_ERROR_LOCKOUT_PERMANENT;
+        if (mCurrentDialog.isAllowDeviceCredentials() && isLockout) {
+            mCurrentDialog.animateToCredentialUI();
+        } else {
+            mCurrentDialog.onError(error);
+        }
     }
 
     @Override
-    public void hideBiometricDialog() {
-        if (DEBUG) Log.d(TAG, "hideBiometricDialog");
+    public void hideAuthenticationDialog() {
+        if (DEBUG) Log.d(TAG, "hideAuthenticationDialog");
 
         mCurrentDialog.dismissFromSystemServer();
     }
@@ -262,7 +290,7 @@
         }
 
         if (DEBUG) {
-            Log.d(TAG, "showDialog, "
+            Log.d(TAG, "showDialog: " + args
                     + " savedState: " + savedState
                     + " mCurrentDialog: " + mCurrentDialog
                     + " newDialog: " + newDialog
@@ -306,6 +334,15 @@
             // to send its pending callback immediately.
             if (savedState.getInt(AuthDialog.KEY_CONTAINER_STATE)
                     != AuthContainerView.STATE_ANIMATING_OUT) {
+                final boolean credentialShowing =
+                        savedState.getBoolean(AuthDialog.KEY_CREDENTIAL_SHOWING);
+                if (credentialShowing) {
+                    // TODO: Clean this up
+                    Bundle bundle = (Bundle) mCurrentDialogArgs.arg1;
+                    bundle.putInt(BiometricPrompt.KEY_AUTHENTICATORS_ALLOWED,
+                            Authenticator.TYPE_CREDENTIAL);
+                }
+
                 showDialog(mCurrentDialogArgs, true /* skipAnimation */, savedState);
             }
         }
diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/AuthCredentialPasswordView.java b/packages/SystemUI/src/com/android/systemui/biometrics/AuthCredentialPasswordView.java
new file mode 100644
index 0000000..8df072e
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/biometrics/AuthCredentialPasswordView.java
@@ -0,0 +1,118 @@
+/*
+ * 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.biometrics;
+
+import android.content.Context;
+import android.text.InputType;
+import android.util.AttributeSet;
+import android.view.KeyEvent;
+import android.view.inputmethod.EditorInfo;
+import android.view.inputmethod.InputMethodManager;
+import android.widget.EditText;
+import android.widget.TextView;
+
+import com.android.internal.widget.LockPatternChecker;
+import com.android.internal.widget.LockPatternUtils;
+import com.android.systemui.R;
+
+/**
+ * Pin and Password UI
+ */
+public class AuthCredentialPasswordView extends AuthCredentialView
+        implements TextView.OnEditorActionListener {
+
+    private static final String TAG = "BiometricPrompt/AuthCredentialPasswordView";
+
+    private final InputMethodManager mImm;
+    private EditText mPasswordField;
+
+    public AuthCredentialPasswordView(Context context,
+            AttributeSet attrs) {
+        super(context, attrs);
+        mImm = mContext.getSystemService(InputMethodManager.class);
+    }
+
+    @Override
+    protected void onFinishInflate() {
+        super.onFinishInflate();
+        mPasswordField = findViewById(R.id.lockPassword);
+        mPasswordField.setOnEditorActionListener(this);
+        mPasswordField.setOnKeyListener((v, keyCode, event) -> {
+            if (keyCode != KeyEvent.KEYCODE_BACK) {
+                return false;
+            }
+            if (event.getAction() == KeyEvent.ACTION_UP) {
+                mContainerView.animateAway(AuthDialogCallback.DISMISSED_USER_CANCELED);
+            }
+            return true;
+        });
+    }
+
+    @Override
+    protected void onAttachedToWindow() {
+        super.onAttachedToWindow();
+
+        if (mCredentialType == Utils.CREDENTIAL_PIN) {
+            mPasswordField.setInputType(
+                    InputType.TYPE_CLASS_NUMBER | InputType.TYPE_NUMBER_VARIATION_PASSWORD);
+        }
+
+        // Wait a bit to focus the field so the focusable flag on the window is already set then.
+        post(() -> {
+            mPasswordField.requestFocus();
+            mImm.showSoftInput(mPasswordField, InputMethodManager.SHOW_IMPLICIT);
+        });
+    }
+
+    @Override
+    public boolean onEditorAction(TextView v, int actionId, KeyEvent event) {
+        // Check if this was the result of hitting the enter key
+        final boolean isSoftImeEvent = event == null
+                && (actionId == EditorInfo.IME_NULL
+                || actionId == EditorInfo.IME_ACTION_DONE
+                || actionId == EditorInfo.IME_ACTION_NEXT);
+        final boolean isKeyboardEnterKey = event != null
+                && KeyEvent.isConfirmKey(event.getKeyCode())
+                && event.getAction() == KeyEvent.ACTION_DOWN;
+        if (isSoftImeEvent || isKeyboardEnterKey) {
+            checkPasswordAndUnlock();
+            return true;
+        }
+        return false;
+    }
+
+    private void checkPasswordAndUnlock() {
+        final byte[] password = LockPatternUtils.charSequenceToByteArray(mPasswordField.getText());
+        if (password == null || password.length == 0) {
+            return;
+        }
+
+        mPendingLockCheck = LockPatternChecker.checkPassword(mLockPatternUtils,
+                password, mUserId, this::onCredentialChecked);
+    }
+
+    @Override
+    protected void onCredentialChecked(boolean matched, int timeoutMs) {
+        super.onCredentialChecked(matched, timeoutMs);
+
+        if (matched) {
+            mImm.hideSoftInputFromWindow(getWindowToken(), 0 /* flags */);
+        } else {
+            mPasswordField.setText("");
+        }
+    }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/AuthCredentialPatternView.java b/packages/SystemUI/src/com/android/systemui/biometrics/AuthCredentialPatternView.java
new file mode 100644
index 0000000..6c36f82
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/biometrics/AuthCredentialPatternView.java
@@ -0,0 +1,102 @@
+/*
+ * 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.biometrics;
+
+import android.content.Context;
+import android.util.AttributeSet;
+
+import com.android.internal.widget.LockPatternChecker;
+import com.android.internal.widget.LockPatternUtils;
+import com.android.internal.widget.LockPatternView;
+import com.android.systemui.R;
+
+import java.util.List;
+
+/**
+ * Pattern UI
+ */
+public class AuthCredentialPatternView extends AuthCredentialView {
+
+    private LockPatternView mLockPatternView;
+
+    private class UnlockPatternListener implements LockPatternView.OnPatternListener {
+
+        @Override
+        public void onPatternStart() {
+
+        }
+
+        @Override
+        public void onPatternCleared() {
+
+        }
+
+        @Override
+        public void onPatternCellAdded(List<LockPatternView.Cell> pattern) {
+
+        }
+
+        @Override
+        public void onPatternDetected(List<LockPatternView.Cell> pattern) {
+            if (mPendingLockCheck != null) {
+                mPendingLockCheck.cancel(false);
+            }
+
+            mLockPatternView.setEnabled(false);
+
+            if (pattern.size() < LockPatternUtils.MIN_PATTERN_REGISTER_FAIL) {
+                // Pattern size is less than the minimum, do not count it as a failed attempt.
+                onPatternChecked(false /* matched */, 0 /* timeoutMs */);
+                return;
+            }
+
+            mPendingLockCheck = LockPatternChecker.checkPattern(
+                    mLockPatternUtils,
+                    pattern,
+                    mUserId,
+                    this::onPatternChecked);
+        }
+
+        private void onPatternChecked(boolean matched, int timeoutMs) {
+            AuthCredentialPatternView.this.onCredentialChecked(matched, timeoutMs);
+            if (timeoutMs > 0) {
+                mLockPatternView.setEnabled(false);
+            } else {
+                mLockPatternView.setEnabled(true);
+            }
+        }
+    }
+
+    @Override
+    protected void onErrorTimeoutFinish() {
+        super.onErrorTimeoutFinish();
+        mLockPatternView.setEnabled(true);
+    }
+
+    public AuthCredentialPatternView(Context context, AttributeSet attrs) {
+        super(context, attrs);
+    }
+
+    @Override
+    protected void onFinishInflate() {
+        super.onFinishInflate();
+        mLockPatternView = findViewById(R.id.lockPattern);
+        mLockPatternView.setOnPatternListener(new UnlockPatternListener());
+        mLockPatternView.setInStealthMode(!mLockPatternUtils.isVisiblePatternEnabled(mUserId));
+        mLockPatternView.setTactileFeedbackEnabled(mLockPatternUtils.isTactileFeedbackEnabled());
+    }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/AuthCredentialView.java b/packages/SystemUI/src/com/android/systemui/biometrics/AuthCredentialView.java
new file mode 100644
index 0000000..8c8611e
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/biometrics/AuthCredentialView.java
@@ -0,0 +1,265 @@
+/*
+ * 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.biometrics;
+
+import android.content.Context;
+import android.hardware.biometrics.BiometricPrompt;
+import android.os.AsyncTask;
+import android.os.Bundle;
+import android.os.CountDownTimer;
+import android.os.Handler;
+import android.os.Looper;
+import android.os.SystemClock;
+import android.text.TextUtils;
+import android.util.AttributeSet;
+import android.view.View;
+import android.view.accessibility.AccessibilityManager;
+import android.widget.LinearLayout;
+import android.widget.TextView;
+
+import com.android.internal.widget.LockPatternUtils;
+import com.android.systemui.Interpolators;
+import com.android.systemui.R;
+
+/**
+ * Abstract base class for Pin, Pattern, or Password authentication, for
+ * {@link BiometricPrompt.Builder#setDeviceCredentialAllowed(boolean)}
+ */
+public abstract class AuthCredentialView extends LinearLayout {
+
+    private static final String TAG = "BiometricPrompt/AuthCredentialView";
+    private static final int ERROR_DURATION_MS = 3000;
+
+    private final AccessibilityManager mAccessibilityManager;
+
+    protected final Handler mHandler;
+
+    private Bundle mBiometricPromptBundle;
+    private AuthPanelController mPanelController;
+    private boolean mShouldAnimatePanel;
+    private boolean mShouldAnimateContents;
+
+    private TextView mTitleView;
+    private TextView mSubtitleView;
+    private TextView mDescriptionView;
+    protected TextView mErrorView;
+
+    protected @Utils.CredentialType int mCredentialType;
+    protected final LockPatternUtils mLockPatternUtils;
+    protected AuthContainerView mContainerView;
+    protected Callback mCallback;
+    protected AsyncTask<?, ?, ?> mPendingLockCheck;
+    protected int mUserId;
+    protected ErrorTimer mErrorTimer;
+
+    interface Callback {
+        void onCredentialMatched();
+    }
+
+    protected static class ErrorTimer extends CountDownTimer {
+        private final TextView mErrorView;
+        private final Context mContext;
+
+        /**
+         * @param millisInFuture    The number of millis in the future from the call
+         *                          to {@link #start()} until the countdown is done and {@link
+         *                          #onFinish()}
+         *                          is called.
+         * @param countDownInterval The interval along the way to receive
+         *                          {@link #onTick(long)} callbacks.
+         */
+        public ErrorTimer(Context context, long millisInFuture, long countDownInterval,
+                TextView errorView) {
+            super(millisInFuture, countDownInterval);
+            mErrorView = errorView;
+            mContext = context;
+        }
+
+        @Override
+        public void onTick(long millisUntilFinished) {
+            final int secondsCountdown = (int) (millisUntilFinished / 1000);
+            mErrorView.setText(mContext.getString(
+                    R.string.biometric_dialog_credential_too_many_attempts, secondsCountdown));
+        }
+
+        @Override
+        public void onFinish() {
+            mErrorView.setText("");
+        }
+    }
+
+    protected final Runnable mClearErrorRunnable = new Runnable() {
+        @Override
+        public void run() {
+            mErrorView.setText("");
+        }
+    };
+
+    public AuthCredentialView(Context context, AttributeSet attrs) {
+        super(context, attrs);
+
+        mLockPatternUtils = new LockPatternUtils(mContext);
+        mHandler = new Handler(Looper.getMainLooper());
+        mAccessibilityManager = mContext.getSystemService(AccessibilityManager.class);
+    }
+
+    protected void showError(String error) {
+        mHandler.removeCallbacks(mClearErrorRunnable);
+        mErrorView.setText(error);
+        mHandler.postDelayed(mClearErrorRunnable, ERROR_DURATION_MS);
+    }
+
+    private void setTextOrHide(TextView view, String string) {
+        if (TextUtils.isEmpty(string)) {
+            view.setVisibility(View.GONE);
+        } else {
+            view.setText(string);
+        }
+
+        Utils.notifyAccessibilityContentChanged(mAccessibilityManager, this);
+    }
+
+    private void setText(TextView view, String string) {
+        view.setText(string);
+    }
+
+    void setUser(int user) {
+        mUserId = user;
+    }
+
+    void setCallback(Callback callback) {
+        mCallback = callback;
+    }
+
+    void setBiometricPromptBundle(Bundle bundle) {
+        mBiometricPromptBundle = bundle;
+    }
+
+    void setPanelController(AuthPanelController panelController, boolean animatePanel) {
+        mPanelController = panelController;
+        mShouldAnimatePanel = animatePanel;
+    }
+
+    void setShouldAnimateContents(boolean animateContents) {
+        mShouldAnimateContents = animateContents;
+    }
+
+    void setContainerView(AuthContainerView containerView) {
+        mContainerView = containerView;
+    }
+
+    @Override
+    protected void onAttachedToWindow() {
+        super.onAttachedToWindow();
+
+        mCredentialType = Utils.getCredentialType(mContext, mUserId);
+
+        setText(mTitleView, mBiometricPromptBundle.getString(BiometricPrompt.KEY_TITLE));
+        setTextOrHide(mSubtitleView,
+                mBiometricPromptBundle.getString(BiometricPrompt.KEY_SUBTITLE));
+        setTextOrHide(mDescriptionView,
+                mBiometricPromptBundle.getString(BiometricPrompt.KEY_DESCRIPTION));
+
+        // Only animate this if we're transitioning from a biometric view.
+        if (mShouldAnimateContents) {
+            setTranslationY(getResources()
+                    .getDimension(R.dimen.biometric_dialog_credential_translation_offset));
+            setAlpha(0);
+
+            postOnAnimation(() -> {
+                animate().translationY(0)
+                        .setDuration(AuthDialog.ANIMATE_CREDENTIAL_INITIAL_DURATION_MS)
+                        .alpha(1.f)
+                        .setInterpolator(Interpolators.LINEAR_OUT_SLOW_IN)
+                        .withLayer()
+                        .start();
+            });
+        }
+    }
+
+    @Override
+    protected void onDetachedFromWindow() {
+        super.onDetachedFromWindow();
+        if (mErrorTimer != null) {
+            mErrorTimer.cancel();
+        }
+    }
+
+    @Override
+    protected void onFinishInflate() {
+        super.onFinishInflate();
+        mTitleView = findViewById(R.id.title);
+        mSubtitleView = findViewById(R.id.subtitle);
+        mDescriptionView = findViewById(R.id.description);
+        mErrorView = findViewById(R.id.error);
+    }
+
+    @Override
+    protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
+        super.onLayout(changed, left, top, right, bottom);
+
+        if (mShouldAnimatePanel) {
+            // Credential view is always full screen.
+            mPanelController.setUseFullScreen(true);
+            mPanelController.updateForContentDimensions(mPanelController.getContainerWidth(),
+                    mPanelController.getContainerHeight(), 0 /* animateDurationMs */);
+            mShouldAnimatePanel = false;
+        }
+    }
+
+    protected void onErrorTimeoutFinish() {}
+
+    protected void onCredentialChecked(boolean matched, int timeoutMs) {
+        if (matched) {
+            mClearErrorRunnable.run();
+            mCallback.onCredentialMatched();
+        } else {
+            if (timeoutMs > 0) {
+                mHandler.removeCallbacks(mClearErrorRunnable);
+                long deadline = mLockPatternUtils.setLockoutAttemptDeadline(mUserId, timeoutMs);
+                mErrorTimer = new ErrorTimer(mContext,
+                        deadline - SystemClock.elapsedRealtime(),
+                        LockPatternUtils.FAILED_ATTEMPT_COUNTDOWN_INTERVAL_MS,
+                        mErrorView) {
+                    @Override
+                    public void onFinish() {
+                        onErrorTimeoutFinish();
+                        mClearErrorRunnable.run();
+                    }
+                };
+                mErrorTimer.start();
+            } else {
+                final int error;
+                switch (mCredentialType) {
+                    case Utils.CREDENTIAL_PIN:
+                        error = R.string.biometric_dialog_wrong_pin;
+                        break;
+                    case Utils.CREDENTIAL_PATTERN:
+                        error = R.string.biometric_dialog_wrong_pattern;
+                        break;
+                    case Utils.CREDENTIAL_PASSWORD:
+                        error = R.string.biometric_dialog_wrong_password;
+                        break;
+                    default:
+                        error = R.string.biometric_dialog_wrong_password;
+                        break;
+                }
+                showError(getResources().getString(error));
+            }
+        }
+    }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/AuthDialog.java b/packages/SystemUI/src/com/android/systemui/biometrics/AuthDialog.java
index edb2953..ca95f9d 100644
--- a/packages/SystemUI/src/com/android/systemui/biometrics/AuthDialog.java
+++ b/packages/SystemUI/src/com/android/systemui/biometrics/AuthDialog.java
@@ -31,6 +31,8 @@
 public interface AuthDialog {
 
     String KEY_CONTAINER_STATE = "container_state";
+    String KEY_BIOMETRIC_SHOWING = "biometric_showing";
+    String KEY_CREDENTIAL_SHOWING = "credential_showing";
 
     String KEY_BIOMETRIC_TRY_AGAIN_VISIBILITY = "try_agian_visibility";
     String KEY_BIOMETRIC_STATE = "state";
@@ -40,17 +42,38 @@
     String KEY_BIOMETRIC_DIALOG_SIZE = "size";
 
     int SIZE_UNKNOWN = 0;
+    /**
+     * Minimal UI, showing only biometric icon.
+     */
     int SIZE_SMALL = 1;
+    /**
+     * Normal-sized biometric UI, showing title, icon, buttons, etc.
+     */
     int SIZE_MEDIUM = 2;
+    /**
+     * Full-screen credential UI.
+     */
     int SIZE_LARGE = 3;
     @Retention(RetentionPolicy.SOURCE)
     @IntDef({SIZE_UNKNOWN, SIZE_SMALL, SIZE_MEDIUM, SIZE_LARGE})
     @interface DialogSize {}
 
     /**
-     * Animation duration, e.g. small to medium dialog, icon translation, etc.
+     * Animation duration, from small to medium dialog, including back panel, icon translation, etc
      */
-    int ANIMATE_DURATION_MS = 150;
+    int ANIMATE_SMALL_TO_MEDIUM_DURATION_MS = 150;
+    /**
+     * Animation duration from medium to large dialog, including biometric fade out, back panel, etc
+     */
+    int ANIMATE_MEDIUM_TO_LARGE_DURATION_MS = 450;
+    /**
+     * Delay before notifying {@link AuthCredentialView} to start animating in.
+     */
+    int ANIMATE_CREDENTIAL_START_DELAY_MS = ANIMATE_MEDIUM_TO_LARGE_DURATION_MS * 2 / 3;
+    /**
+     * Animation duration when sliding in credential UI
+     */
+    int ANIMATE_CREDENTIAL_INITIAL_DURATION_MS = 150;
 
     /**
      * Show the dialog.
@@ -101,4 +124,14 @@
      * Get the client's package name
      */
     String getOpPackageName();
+
+    /**
+     * Animate to credential UI. Typically called after biometric is locked out.
+     */
+    void animateToCredentialUI();
+
+    /**
+     * @return true if device credential is allowed.
+     */
+    boolean isAllowDeviceCredentials();
 }
diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/AuthDialogCallback.java b/packages/SystemUI/src/com/android/systemui/biometrics/AuthDialogCallback.java
index 70752f5..12bb122 100644
--- a/packages/SystemUI/src/com/android/systemui/biometrics/AuthDialogCallback.java
+++ b/packages/SystemUI/src/com/android/systemui/biometrics/AuthDialogCallback.java
@@ -27,17 +27,18 @@
     int DISMISSED_USER_CANCELED = 1;
     int DISMISSED_BUTTON_NEGATIVE = 2;
     int DISMISSED_BUTTON_POSITIVE = 3;
-
-    int DISMISSED_AUTHENTICATED = 4;
+    int DISMISSED_BIOMETRIC_AUTHENTICATED = 4;
     int DISMISSED_ERROR = 5;
     int DISMISSED_BY_SYSTEM_SERVER = 6;
+    int DISMISSED_CREDENTIAL_AUTHENTICATED = 7;
 
     @IntDef({DISMISSED_USER_CANCELED,
             DISMISSED_BUTTON_NEGATIVE,
             DISMISSED_BUTTON_POSITIVE,
-            DISMISSED_AUTHENTICATED,
+            DISMISSED_BIOMETRIC_AUTHENTICATED,
             DISMISSED_ERROR,
-            DISMISSED_BY_SYSTEM_SERVER})
+            DISMISSED_BY_SYSTEM_SERVER,
+            DISMISSED_CREDENTIAL_AUTHENTICATED})
     @interface DismissedReason {}
 
     /**
@@ -50,4 +51,9 @@
      * Invoked when the "try again" button is clicked
      */
     void onTryAgainPressed();
+
+    /**
+     * Invoked when the "use password" button is clicked
+     */
+    void onDeviceCredentialPressed();
 }
diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/AuthPanelController.java b/packages/SystemUI/src/com/android/systemui/biometrics/AuthPanelController.java
index 55ba049..2b8b586 100644
--- a/packages/SystemUI/src/com/android/systemui/biometrics/AuthPanelController.java
+++ b/packages/SystemUI/src/com/android/systemui/biometrics/AuthPanelController.java
@@ -16,15 +16,17 @@
 
 package com.android.systemui.biometrics;
 
+import android.animation.AnimatorSet;
 import android.animation.ValueAnimator;
 import android.content.Context;
+import android.graphics.Color;
 import android.graphics.Outline;
 import android.util.Log;
 import android.view.View;
 import android.view.ViewOutlineProvider;
+import android.view.animation.AccelerateDecelerateInterpolator;
 
 import com.android.systemui.R;
-import com.android.systemui.biometrics.AuthDialog;
 
 /**
  * Controls the back panel and its animations for the BiometricPrompt UI.
@@ -36,8 +38,9 @@
 
     private final Context mContext;
     private final View mPanelView;
-    private final float mCornerRadius;
-    private final int mBiometricMargin;
+    private final boolean mIsManagedProfile;
+
+    private boolean mUseFullScreen;
 
     private int mContainerWidth;
     private int mContainerHeight;
@@ -45,14 +48,23 @@
     private int mContentWidth;
     private int mContentHeight;
 
+    private float mCornerRadius;
+    private int mMargin;
+
     @Override
     public void getOutline(View view, Outline outline) {
         final int left = (mContainerWidth - mContentWidth) / 2;
         final int right = mContainerWidth - left;
+
+        // If the content fits within the container, shrink the height to wrap the content.
+        // Otherwise, set the outline to be the display size minus the margin - the content within
+        // is scrollable.
         final int top = mContentHeight < mContainerHeight
-                ? mContainerHeight - mContentHeight - mBiometricMargin
-                : mBiometricMargin;
-        final int bottom = mContainerHeight - mBiometricMargin;
+                ? mContainerHeight - mContentHeight - mMargin
+                : mMargin;
+
+        // TODO(b/139954942) Likely don't need to "+1" after we resolve the navbar styling.
+        final int bottom = mContainerHeight - mMargin + 1;
         outline.setRoundRect(left, top, right, bottom, mCornerRadius);
     }
 
@@ -64,11 +76,34 @@
         mContainerHeight = containerHeight;
     }
 
-    public void updateForContentDimensions(int contentWidth, int contentHeight, boolean animate) {
+    public void setUseFullScreen(boolean fullScreen) {
+        mUseFullScreen = fullScreen;
+    }
+
+    public ValueAnimator getTranslationAnimator(float relativeTranslationY) {
+        final ValueAnimator animator = ValueAnimator.ofFloat(
+                mPanelView.getY(), mPanelView.getY() - relativeTranslationY);
+        animator.addUpdateListener(animation -> {
+            final float translation = (float) animation.getAnimatedValue();
+            mPanelView.setTranslationY(translation);
+        });
+        return animator;
+    }
+
+    public ValueAnimator getAlphaAnimator(float alpha) {
+        final ValueAnimator animator = ValueAnimator.ofFloat(mPanelView.getAlpha(), alpha);
+        animator.addUpdateListener(animation -> {
+            mPanelView.setAlpha((float) animation.getAnimatedValue());
+        });
+        return animator;
+    }
+
+    public void updateForContentDimensions(int contentWidth, int contentHeight,
+            int animateDurationMs) {
         if (DEBUG) {
             Log.v(TAG, "Content Width: " + contentWidth
                     + " Height: " + contentHeight
-                    + " Animate: " + animate);
+                    + " Animate: " + animateDurationMs);
         }
 
         if (mContainerWidth == 0 || mContainerHeight == 0) {
@@ -76,27 +111,86 @@
             return;
         }
 
-        if (animate) {
+        final int margin = mUseFullScreen ? 0 : (int) mContext.getResources()
+                .getDimension(R.dimen.biometric_dialog_border_padding);
+        final float cornerRadius = mUseFullScreen ? 0 : mContext.getResources()
+                .getDimension(R.dimen.biometric_dialog_corner_size);
+
+        // When going to full-screen for managed profiles, fade away so the managed profile
+        // background behind this view becomes visible.
+        final boolean shouldFadeAway = mUseFullScreen && mIsManagedProfile;
+        final int alpha = shouldFadeAway ? 0 : 255;
+        final float elevation = shouldFadeAway ? 0 :
+                mContext.getResources().getDimension(R.dimen.biometric_dialog_elevation);
+
+        if (animateDurationMs > 0) {
+            // Animate margin
+            ValueAnimator marginAnimator = ValueAnimator.ofInt(mMargin, margin);
+            marginAnimator.addUpdateListener((animation) -> {
+                mMargin = (int) animation.getAnimatedValue();
+            });
+
+            // Animate corners
+            ValueAnimator cornerAnimator = ValueAnimator.ofFloat(mCornerRadius, cornerRadius);
+            cornerAnimator.addUpdateListener((animation) -> {
+                mCornerRadius = (float) animation.getAnimatedValue();
+            });
+
+            // Animate height
             ValueAnimator heightAnimator = ValueAnimator.ofInt(mContentHeight, contentHeight);
-            heightAnimator.setDuration(AuthDialog.ANIMATE_DURATION_MS);
             heightAnimator.addUpdateListener((animation) -> {
                 mContentHeight = (int) animation.getAnimatedValue();
                 mPanelView.invalidateOutline();
             });
             heightAnimator.start();
+
+            // Animate width
+            ValueAnimator widthAnimator = ValueAnimator.ofInt(mContentWidth, contentWidth);
+            widthAnimator.addUpdateListener((animation) -> {
+                mContentWidth = (int) animation.getAnimatedValue();
+            });
+
+            // Animate background
+            ValueAnimator alphaAnimator = ValueAnimator.ofInt(
+                    mPanelView.getBackground().getAlpha(), alpha);
+            alphaAnimator.addUpdateListener((animation) -> {
+                if (shouldFadeAway) {
+                    mPanelView.getBackground().setAlpha((int) animation.getAnimatedValue());
+                }
+            });
+
+            // Play together
+            AnimatorSet as = new AnimatorSet();
+            as.setDuration(animateDurationMs);
+            as.setInterpolator(new AccelerateDecelerateInterpolator());
+            as.playTogether(cornerAnimator, widthAnimator, marginAnimator, alphaAnimator);
+            as.start();
+
         } else {
+            mMargin = margin;
+            mCornerRadius = cornerRadius;
             mContentWidth = contentWidth;
             mContentHeight = contentHeight;
+            mPanelView.getBackground().setAlpha(alpha);
             mPanelView.invalidateOutline();
         }
     }
 
-    AuthPanelController(Context context, View panelView) {
+    int getContainerWidth() {
+        return mContainerWidth;
+    }
+
+    int getContainerHeight() {
+        return mContainerHeight;
+    }
+
+    AuthPanelController(Context context, View panelView, boolean isManagedProfile) {
         mContext = context;
         mPanelView = panelView;
+        mIsManagedProfile = isManagedProfile;
         mCornerRadius = context.getResources()
                 .getDimension(R.dimen.biometric_dialog_corner_size);
-        mBiometricMargin = (int) context.getResources()
+        mMargin = (int) context.getResources()
                 .getDimension(R.dimen.biometric_dialog_border_padding);
         mPanelView.setOutlineProvider(this);
         mPanelView.setClipToOutline(true);
diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/Utils.java b/packages/SystemUI/src/com/android/systemui/biometrics/Utils.java
index e00cf6a..d6f830d 100644
--- a/packages/SystemUI/src/com/android/systemui/biometrics/Utils.java
+++ b/packages/SystemUI/src/com/android/systemui/biometrics/Utils.java
@@ -18,14 +18,36 @@
 
 import static android.view.accessibility.AccessibilityEvent.CONTENT_CHANGE_TYPE_SUBTREE;
 
+import android.annotation.IntDef;
+import android.app.admin.DevicePolicyManager;
 import android.content.Context;
+import android.hardware.biometrics.Authenticator;
+import android.hardware.biometrics.BiometricPrompt;
+import android.os.Bundle;
+import android.os.UserManager;
 import android.util.DisplayMetrics;
 import android.view.View;
 import android.view.ViewGroup;
 import android.view.accessibility.AccessibilityEvent;
 import android.view.accessibility.AccessibilityManager;
 
+import com.android.internal.widget.LockPatternUtils;
+import com.android.systemui.R;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+
 public class Utils {
+
+    public static final int CREDENTIAL_PIN = 1;
+    public static final int CREDENTIAL_PATTERN = 2;
+    public static final int CREDENTIAL_PASSWORD = 3;
+
+    @Retention(RetentionPolicy.SOURCE)
+    @IntDef({CREDENTIAL_PIN, CREDENTIAL_PATTERN, CREDENTIAL_PASSWORD})
+    @interface CredentialType {}
+
+
     static float dpToPixels(Context context, float dp) {
         return dp * ((float) context.getResources().getDisplayMetrics().densityDpi
                 / DisplayMetrics.DENSITY_DEFAULT);
@@ -46,4 +68,41 @@
         view.sendAccessibilityEventUnchecked(event);
         view.notifySubtreeAccessibilityStateChanged(view, view, CONTENT_CHANGE_TYPE_SUBTREE);
     }
+
+    static boolean isDeviceCredentialAllowed(Bundle biometricPromptBundle) {
+        final int authenticators = getAuthenticators(biometricPromptBundle);
+        return (authenticators & Authenticator.TYPE_CREDENTIAL) != 0;
+    }
+
+    static boolean isBiometricAllowed(Bundle biometricPromptBundle) {
+        final int authenticators = getAuthenticators(biometricPromptBundle);
+        return (authenticators & Authenticator.TYPE_BIOMETRIC) != 0;
+    }
+
+    static int getAuthenticators(Bundle biometricPromptBundle) {
+        return biometricPromptBundle.getInt(BiometricPrompt.KEY_AUTHENTICATORS_ALLOWED);
+    }
+
+    static @CredentialType int getCredentialType(Context context, int userId) {
+        final LockPatternUtils lpu = new LockPatternUtils(context);
+        switch (lpu.getKeyguardStoredPasswordQuality(userId)) {
+            case DevicePolicyManager.PASSWORD_QUALITY_SOMETHING:
+                return CREDENTIAL_PATTERN;
+            case DevicePolicyManager.PASSWORD_QUALITY_NUMERIC:
+            case DevicePolicyManager.PASSWORD_QUALITY_NUMERIC_COMPLEX:
+                return CREDENTIAL_PIN;
+            case DevicePolicyManager.PASSWORD_QUALITY_ALPHABETIC:
+            case DevicePolicyManager.PASSWORD_QUALITY_ALPHANUMERIC:
+            case DevicePolicyManager.PASSWORD_QUALITY_COMPLEX:
+            case DevicePolicyManager.PASSWORD_QUALITY_MANAGED:
+                return CREDENTIAL_PASSWORD;
+            default:
+                return CREDENTIAL_PASSWORD;
+        }
+    }
+
+    static boolean isManagedProfile(Context context, int userId) {
+        final UserManager userManager = context.getSystemService(UserManager.class);
+        return userManager.isManagedProfile(userId);
+    }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/bubbles/BubbleController.java b/packages/SystemUI/src/com/android/systemui/bubbles/BubbleController.java
index 8240345..9568a18 100644
--- a/packages/SystemUI/src/com/android/systemui/bubbles/BubbleController.java
+++ b/packages/SystemUI/src/com/android/systemui/bubbles/BubbleController.java
@@ -18,7 +18,6 @@
 
 import static android.app.Notification.FLAG_AUTOGROUP_SUMMARY;
 import static android.app.Notification.FLAG_BUBBLE;
-import static android.content.pm.ActivityInfo.DOCUMENT_LAUNCH_ALWAYS;
 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;
@@ -569,7 +568,8 @@
                     if (mStackView != null) {
                         mStackView.updateDotVisibility(entry.key);
                     }
-                    mNotificationEntryManager.updateNotifications();
+                    mNotificationEntryManager.updateNotifications(
+                            "BubbleController.onNotificationRemoveRequested");
                     return true;
                 } else if (!userRemovedNotif && entry != null) {
                     // This wasn't a user removal so we should remove the bubble as well
@@ -609,7 +609,8 @@
                 mBubbleData.addSummaryToSuppress(summary.notification.getGroupKey(),
                         summary.key);
                 // Tell shade to update for the suppression
-                mNotificationEntryManager.updateNotifications();
+                mNotificationEntryManager.updateNotifications(
+                        "BubbleController.handleSummaryRemovalInterception");
             }
             return !isAutogroupSummary;
         } else {
@@ -760,7 +761,8 @@
                 mStackView.setExpanded(true);
             }
 
-            mNotificationEntryManager.updateNotifications();
+            mNotificationEntryManager.updateNotifications(
+                    "BubbleData.Listener.applyUpdate");
             updateStack();
 
             if (DEBUG_BUBBLE_CONTROLLER) {
@@ -962,16 +964,6 @@
                     + intent);
             return false;
         }
-        if (info.documentLaunchMode != DOCUMENT_LAUNCH_ALWAYS) {
-            Log.w(TAG, "Unable to send as bubble -- activity is not documentLaunchMode=always "
-                    + "for intent: " + intent);
-            return false;
-        }
-        if ((info.flags & ActivityInfo.FLAG_ALLOW_EMBEDDED) == 0) {
-            Log.w(TAG, "Unable to send as bubble -- activity is not embeddable for intent: "
-                    + intent);
-            return false;
-        }
         return true;
     }
 
diff --git a/packages/SystemUI/src/com/android/systemui/bubbles/BubbleExpandedView.java b/packages/SystemUI/src/com/android/systemui/bubbles/BubbleExpandedView.java
index 521ebde..6f953d5 100644
--- a/packages/SystemUI/src/com/android/systemui/bubbles/BubbleExpandedView.java
+++ b/packages/SystemUI/src/com/android/systemui/bubbles/BubbleExpandedView.java
@@ -16,6 +16,8 @@
 
 package com.android.systemui.bubbles;
 
+import static android.content.Intent.FLAG_ACTIVITY_MULTIPLE_TASK;
+import static android.content.Intent.FLAG_ACTIVITY_NEW_DOCUMENT;
 import static android.view.Display.INVALID_DISPLAY;
 
 import static com.android.systemui.bubbles.BubbleDebugConfig.DEBUG_BUBBLE_EXPANDED_VIEW;
@@ -128,8 +130,12 @@
                             Log.d(TAG, "onActivityViewReady: calling startActivity, "
                                     + "bubble=" + getBubbleKey());
                         }
+                        Intent fillInIntent = new Intent();
+                        // Apply flags to make behaviour match documentLaunchMode=always.
+                        fillInIntent.addFlags(FLAG_ACTIVITY_NEW_DOCUMENT);
+                        fillInIntent.addFlags(FLAG_ACTIVITY_MULTIPLE_TASK);
                         try {
-                            mActivityView.startActivity(mBubbleIntent, options);
+                            mActivityView.startActivity(mBubbleIntent, fillInIntent, options);
                         } catch (RuntimeException e) {
                             // If there's a runtime exception here then there's something
                             // wrong with the intent, we can't really recover / try to populate
diff --git a/packages/SystemUI/src/com/android/systemui/classifier/FalsingLog.java b/packages/SystemUI/src/com/android/systemui/classifier/FalsingLog.java
index cb7c998..8105c6a 100644
--- a/packages/SystemUI/src/com/android/systemui/classifier/FalsingLog.java
+++ b/packages/SystemUI/src/com/android/systemui/classifier/FalsingLog.java
@@ -37,7 +37,7 @@
  *  adb shell setprop debug.falsing_log true
  *
  * The log gets dumped as part of the SystemUI services. To dump on demand:
- *  adb shell dumpsys activity service com.android.systemui SystemBars | grep -A 999 FALSING | less
+ *  adb shell dumpsys activity service com.android.systemui StatusBar | grep -A 999 FALSING | less
  *
  * To dump into logcat:
  *  adb shell setprop debug.falsing_logcat true
diff --git a/packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsComponent.java b/packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsComponent.java
index e8ef454..c11127d 100644
--- a/packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsComponent.java
+++ b/packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsComponent.java
@@ -35,6 +35,10 @@
     private Extension<GlobalActions> mExtension;
     private IStatusBarService mBarService;
 
+    public GlobalActionsComponent(Context context) {
+        super(context);
+    }
+
     @Override
     public void start() {
         mBarService = IStatusBarService.Stub.asInterface(
diff --git a/packages/SystemUI/src/com/android/systemui/keyboard/KeyboardUI.java b/packages/SystemUI/src/com/android/systemui/keyboard/KeyboardUI.java
index 7d52a9a..42f455a 100644
--- a/packages/SystemUI/src/com/android/systemui/keyboard/KeyboardUI.java
+++ b/packages/SystemUI/src/com/android/systemui/keyboard/KeyboardUI.java
@@ -117,6 +117,10 @@
 
     private int mState;
 
+    public KeyboardUI(Context context) {
+        super(context);
+    }
+
     @Override
     public void start() {
         mContext = super.mContext;
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardLifecyclesDispatcher.java b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardLifecyclesDispatcher.java
index b3481c5..4a33590 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardLifecyclesDispatcher.java
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardLifecyclesDispatcher.java
@@ -19,9 +19,13 @@
 import android.os.Handler;
 import android.os.Message;
 
+import javax.inject.Inject;
+import javax.inject.Singleton;
+
 /**
  * Dispatches the lifecycles keyguard gets from WindowManager on the main thread.
  */
+@Singleton
 public class KeyguardLifecyclesDispatcher {
 
     static final int SCREEN_TURNING_ON = 0;
@@ -37,6 +41,7 @@
     private final ScreenLifecycle mScreenLifecycle;
     private final WakefulnessLifecycle mWakefulnessLifecycle;
 
+    @Inject
     public KeyguardLifecyclesDispatcher(ScreenLifecycle screenLifecycle,
             WakefulnessLifecycle wakefulnessLifecycle) {
         mScreenLifecycle = screenLifecycle;
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardService.java b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardService.java
index 81247cd..9f4056f 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardService.java
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardService.java
@@ -33,25 +33,30 @@
 import com.android.internal.policy.IKeyguardExitCallback;
 import com.android.internal.policy.IKeyguardService;
 import com.android.internal.policy.IKeyguardStateCallback;
-import com.android.systemui.Dependency;
 import com.android.systemui.SystemUIApplication;
 
+import javax.inject.Inject;
+import javax.inject.Singleton;
+
+@Singleton
 public class KeyguardService extends Service {
     static final String TAG = "KeyguardService";
     static final String PERMISSION = android.Manifest.permission.CONTROL_KEYGUARD;
 
-    private KeyguardViewMediator mKeyguardViewMediator;
-    private KeyguardLifecyclesDispatcher mKeyguardLifecyclesDispatcher;
+    private final KeyguardViewMediator mKeyguardViewMediator;
+    private final KeyguardLifecyclesDispatcher mKeyguardLifecyclesDispatcher;
+
+    @Inject
+    public KeyguardService(KeyguardViewMediator keyguardViewMediator,
+                           KeyguardLifecyclesDispatcher keyguardLifecyclesDispatcher) {
+        super();
+        mKeyguardViewMediator = keyguardViewMediator;
+        mKeyguardLifecyclesDispatcher = keyguardLifecyclesDispatcher;
+    }
 
     @Override
     public void onCreate() {
         ((SystemUIApplication) getApplication()).startServicesIfNeeded();
-        mKeyguardViewMediator =
-                ((SystemUIApplication) getApplication()).getComponent(KeyguardViewMediator.class);
-        mKeyguardLifecyclesDispatcher = new KeyguardLifecyclesDispatcher(
-                Dependency.get(ScreenLifecycle.class),
-                Dependency.get(WakefulnessLifecycle.class));
-
     }
 
     @Override
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java
index d2a9c75..e0270de 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java
@@ -100,6 +100,7 @@
 import java.util.ArrayList;
 
 import javax.inject.Inject;
+import javax.inject.Singleton;
 
 /**
  * Mediates requests related to the keyguard.  This includes queries about the
@@ -142,6 +143,7 @@
  * directly to the keyguard UI is posted to a {@link android.os.Handler} to ensure it is taken on the UI
  * thread of the keyguard.
  */
+@Singleton
 public class KeyguardViewMediator extends SystemUI {
     private static final int KEYGUARD_DISPLAY_TIMEOUT_DELAY_DEFAULT = 30000;
     private static final long KEYGUARD_DONE_PENDING_TIMEOUT_MS = 3000;
@@ -232,7 +234,7 @@
      */
     private PowerManager.WakeLock mShowKeyguardWakeLock;
 
-    private StatusBarKeyguardViewManager mStatusBarKeyguardViewManager;
+    private final StatusBarKeyguardViewManager mStatusBarKeyguardViewManager;
 
     // these are protected by synchronized (this)
 
@@ -315,7 +317,7 @@
      * the keyguard.
      */
     private boolean mWaitingUntilKeyguardVisible = false;
-    private LockPatternUtils mLockPatternUtils;
+    private final LockPatternUtils mLockPatternUtils;
     private boolean mKeyguardDonePending = false;
     private boolean mHideAnimationRun = false;
     private boolean mHideAnimationRunning = false;
@@ -648,29 +650,26 @@
 
         @Override
         public int getBouncerPromptReason() {
-            // TODO(b/140053364)
-            return whitelistIpcs(() -> {
-                int currentUser = ActivityManager.getCurrentUser();
-                boolean trust = mTrustManager.isTrustUsuallyManaged(currentUser);
-                boolean biometrics = mUpdateMonitor.isUnlockingWithBiometricsPossible(currentUser);
-                boolean any = trust || biometrics;
-                KeyguardUpdateMonitor.StrongAuthTracker strongAuthTracker =
-                        mUpdateMonitor.getStrongAuthTracker();
-                int strongAuth = strongAuthTracker.getStrongAuthForUser(currentUser);
+            int currentUser = KeyguardUpdateMonitor.getCurrentUser();
+            boolean trust = mUpdateMonitor.isTrustUsuallyManaged(currentUser);
+            boolean biometrics = mUpdateMonitor.isUnlockingWithBiometricsPossible(currentUser);
+            boolean any = trust || biometrics;
+            KeyguardUpdateMonitor.StrongAuthTracker strongAuthTracker =
+                    mUpdateMonitor.getStrongAuthTracker();
+            int strongAuth = strongAuthTracker.getStrongAuthForUser(currentUser);
 
-                if (any && !strongAuthTracker.hasUserAuthenticatedSinceBoot()) {
-                    return KeyguardSecurityView.PROMPT_REASON_RESTART;
-                } else if (any && (strongAuth & STRONG_AUTH_REQUIRED_AFTER_TIMEOUT) != 0) {
-                    return KeyguardSecurityView.PROMPT_REASON_TIMEOUT;
-                } else if (any && (strongAuth & STRONG_AUTH_REQUIRED_AFTER_DPM_LOCK_NOW) != 0) {
-                    return KeyguardSecurityView.PROMPT_REASON_DEVICE_ADMIN;
-                } else if (trust && (strongAuth & SOME_AUTH_REQUIRED_AFTER_USER_REQUEST) != 0) {
-                    return KeyguardSecurityView.PROMPT_REASON_USER_REQUEST;
-                } else if (any && (strongAuth & STRONG_AUTH_REQUIRED_AFTER_LOCKOUT) != 0) {
-                    return KeyguardSecurityView.PROMPT_REASON_AFTER_LOCKOUT;
-                }
-                return KeyguardSecurityView.PROMPT_REASON_NONE;
-            });
+            if (any && !strongAuthTracker.hasUserAuthenticatedSinceBoot()) {
+                return KeyguardSecurityView.PROMPT_REASON_RESTART;
+            } else if (any && (strongAuth & STRONG_AUTH_REQUIRED_AFTER_TIMEOUT) != 0) {
+                return KeyguardSecurityView.PROMPT_REASON_TIMEOUT;
+            } else if (any && (strongAuth & STRONG_AUTH_REQUIRED_AFTER_DPM_LOCK_NOW) != 0) {
+                return KeyguardSecurityView.PROMPT_REASON_DEVICE_ADMIN;
+            } else if (trust && (strongAuth & SOME_AUTH_REQUIRED_AFTER_USER_REQUEST) != 0) {
+                return KeyguardSecurityView.PROMPT_REASON_USER_REQUEST;
+            } else if (any && (strongAuth & STRONG_AUTH_REQUIRED_AFTER_LOCKOUT) != 0) {
+                return KeyguardSecurityView.PROMPT_REASON_AFTER_LOCKOUT;
+            }
+            return KeyguardSecurityView.PROMPT_REASON_NONE;
         }
 
         @Override
@@ -682,10 +681,20 @@
     };
 
     @Inject
-    public KeyguardViewMediator(FalsingManager falsingManager) {
-        super();
+    public KeyguardViewMediator(
+            Context context,
+            FalsingManager falsingManager,
+            LockPatternUtils lockPatternUtils) {
+        super(context);
 
         mFalsingManager = falsingManager;
+
+        mLockPatternUtils = lockPatternUtils;
+        mStatusBarKeyguardViewManager =
+                SystemUIFactory.getInstance().createStatusBarKeyguardViewManager(
+                        mContext,
+                        mViewMediatorCallback,
+                        mLockPatternUtils);
     }
 
     public void userActivity() {
@@ -699,7 +708,7 @@
 
     private void setupLocked() {
         mPM = (PowerManager) mContext.getSystemService(Context.POWER_SERVICE);
-        mTrustManager = (TrustManager) mContext.getSystemService(Context.TRUST_SERVICE);
+        mTrustManager = mContext.getSystemService(TrustManager.class);
 
         mShowKeyguardWakeLock = mPM.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "show keyguard");
         mShowKeyguardWakeLock.setReferenceCounted(false);
@@ -723,7 +732,6 @@
 
         mUpdateMonitor = Dependency.get(KeyguardUpdateMonitor.class);
 
-        mLockPatternUtils = new LockPatternUtils(mContext);
         KeyguardUpdateMonitor.setCurrentUser(ActivityManager.getCurrentUser());
 
         // Assume keyguard is showing (unless it's disabled) until we know for sure, unless Keyguard
@@ -737,9 +745,6 @@
             setShowingLocked(false /* showing */, true /* forceCallbacks */);
         }
 
-        mStatusBarKeyguardViewManager =
-                SystemUIFactory.getInstance().createStatusBarKeyguardViewManager(mContext,
-                        mViewMediatorCallback, mLockPatternUtils);
         final ContentResolver cr = mContext.getContentResolver();
 
         mDeviceInteractive = mPM.isInteractive();
@@ -789,7 +794,6 @@
         synchronized (this) {
             setupLocked();
         }
-        putComponent(KeyguardViewMediator.class, this);
     }
 
     /**
diff --git a/packages/SystemUI/src/com/android/systemui/media/RingtonePlayer.java b/packages/SystemUI/src/com/android/systemui/media/RingtonePlayer.java
index aebadf9..4c96de2 100644
--- a/packages/SystemUI/src/com/android/systemui/media/RingtonePlayer.java
+++ b/packages/SystemUI/src/com/android/systemui/media/RingtonePlayer.java
@@ -59,6 +59,10 @@
     private final NotificationPlayer mAsyncPlayer = new NotificationPlayer(TAG);
     private final HashMap<IBinder, Client> mClients = new HashMap<IBinder, Client>();
 
+    public RingtonePlayer(Context context) {
+        super(context);
+    }
+
     @Override
     public void start() {
         mAsyncPlayer.setUsesWakeLock(mContext);
diff --git a/packages/SystemUI/src/com/android/systemui/pip/PipUI.java b/packages/SystemUI/src/com/android/systemui/pip/PipUI.java
index 682c76c..f1e801b 100644
--- a/packages/SystemUI/src/com/android/systemui/pip/PipUI.java
+++ b/packages/SystemUI/src/com/android/systemui/pip/PipUI.java
@@ -19,6 +19,7 @@
 import static android.content.pm.PackageManager.FEATURE_LEANBACK_ONLY;
 import static android.content.pm.PackageManager.FEATURE_PICTURE_IN_PICTURE;
 
+import android.content.Context;
 import android.content.pm.PackageManager;
 import android.content.res.Configuration;
 import android.os.UserHandle;
@@ -30,15 +31,24 @@
 import java.io.FileDescriptor;
 import java.io.PrintWriter;
 
+import javax.inject.Inject;
+import javax.inject.Singleton;
+
 /**
  * Controls the picture-in-picture window.
  */
+@Singleton
 public class PipUI extends SystemUI implements CommandQueue.Callbacks {
 
     private BasePipManager mPipManager;
 
     private boolean mSupportsPip;
 
+    @Inject
+    public PipUI(Context context) {
+        super(context);
+    }
+
     @Override
     public void start() {
         PackageManager pm = mContext.getPackageManager();
@@ -59,7 +69,6 @@
         mPipManager.initialize(mContext);
 
         getComponent(CommandQueue.class).addCallback(this);
-        putComponent(PipUI.class, this);
     }
 
     @Override
diff --git a/packages/SystemUI/src/com/android/systemui/power/PowerUI.java b/packages/SystemUI/src/com/android/systemui/power/PowerUI.java
index a258f35..98f0b2a 100644
--- a/packages/SystemUI/src/com/android/systemui/power/PowerUI.java
+++ b/packages/SystemUI/src/com/android/systemui/power/PowerUI.java
@@ -103,7 +103,8 @@
     private final BroadcastDispatcher mBroadcastDispatcher;
 
     @Inject
-    public PowerUI(BroadcastDispatcher broadcastDispatcher) {
+    public PowerUI(Context context, BroadcastDispatcher broadcastDispatcher) {
+        super(context);
         mBroadcastDispatcher = broadcastDispatcher;
     }
 
diff --git a/packages/SystemUI/src/com/android/systemui/qs/TileLayout.java b/packages/SystemUI/src/com/android/systemui/qs/TileLayout.java
index 14addb9..37743ec 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/TileLayout.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/TileLayout.java
@@ -2,6 +2,7 @@
 
 import android.content.Context;
 import android.content.res.Resources;
+import android.provider.Settings;
 import android.util.AttributeSet;
 import android.view.View;
 import android.view.ViewGroup;
@@ -31,6 +32,9 @@
     private boolean mListening;
     protected int mMaxAllowedRows = 3;
 
+    // Prototyping with less rows
+    private final boolean mLessRows;
+
     public TileLayout(Context context) {
         this(context, null);
     }
@@ -38,7 +42,9 @@
     public TileLayout(Context context, AttributeSet attrs) {
         super(context, attrs);
         setFocusableInTouchMode(true);
+        mLessRows = Settings.System.getInt(context.getContentResolver(), "qs_less_rows", 0) != 0;
         updateResources();
+
     }
 
     @Override
@@ -89,6 +95,7 @@
         mCellMarginTop = res.getDimensionPixelSize(R.dimen.qs_tile_margin_top);
         mSidePadding = res.getDimensionPixelOffset(R.dimen.qs_tile_layout_margin_side);
         mMaxAllowedRows = Math.max(1, getResources().getInteger(R.integer.quick_settings_max_rows));
+        if (mLessRows) mMaxAllowedRows = Math.max(1, mMaxAllowedRows - 1);
         if (mColumns != columns) {
             mColumns = columns;
             requestLayout();
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/FlashlightTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/FlashlightTile.java
index 2755e98..dafdd89 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/FlashlightTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/FlashlightTile.java
@@ -101,11 +101,15 @@
             state.slash = new SlashState();
         }
         state.label = mHost.getContext().getString(R.string.quick_settings_flashlight_label);
+        state.secondaryLabel = "";
         if (!mFlashlightController.isAvailable()) {
             state.icon = mIcon;
             state.slash.isSlashed = true;
+            state.secondaryLabel = mContext.getString(
+                    R.string.quick_settings_flashlight_camera_in_use);
             state.contentDescription = mContext.getString(
-                    R.string.accessibility_quick_settings_flashlight_unavailable);
+                    R.string.accessibility_quick_settings_flashlight_unavailable)
+                    + ", " + state.secondaryLabel;
             state.state = Tile.STATE_UNAVAILABLE;
             return;
         }
diff --git a/packages/SystemUI/src/com/android/systemui/recents/OverviewProxyService.java b/packages/SystemUI/src/com/android/systemui/recents/OverviewProxyService.java
index e0ae8ed..3fc1398 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/OverviewProxyService.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/OverviewProxyService.java
@@ -101,6 +101,7 @@
     private static final long MAX_BACKOFF_MILLIS = 10 * 60 * 1000;
 
     private final Context mContext;
+    private final PipUI mPipUI;
     private SysUiState mSysUiState;
     private final Handler mHandler;
     private final NavigationBarController mNavBarController;
@@ -361,8 +362,7 @@
             }
             long token = Binder.clearCallingIdentity();
             try {
-                final PipUI component = SysUiServiceProvider.getComponent(mContext, PipUI.class);
-                component.setShelfHeight(visible, shelfHeight);
+                mPipUI.setShelfHeight(visible, shelfHeight);
             } finally {
                 Binder.restoreCallingIdentity(token);
             }
@@ -479,8 +479,9 @@
     public OverviewProxyService(Context context, DeviceProvisionedController provisionController,
             NavigationBarController navBarController, NavigationModeController navModeController,
             StatusBarWindowController statusBarWinController,
-            SysUiState sysUiState) {
+            SysUiState sysUiState, PipUI pipUI) {
         mContext = context;
+        mPipUI = pipUI;
         mHandler = new Handler();
         mNavBarController = navBarController;
         mStatusBarWinController = statusBarWinController;
diff --git a/packages/SystemUI/src/com/android/systemui/recents/Recents.java b/packages/SystemUI/src/com/android/systemui/recents/Recents.java
index a1b4a93..0a8264b 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/Recents.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/Recents.java
@@ -17,6 +17,7 @@
 package com.android.systemui.recents;
 
 import android.content.ContentResolver;
+import android.content.Context;
 import android.content.res.Configuration;
 import android.graphics.Rect;
 import android.provider.Settings;
@@ -37,7 +38,8 @@
     private final RecentsImplementation mImpl;
 
     @Inject
-    public Recents(RecentsImplementation impl) {
+    public Recents(Context context, RecentsImplementation impl) {
+        super(context);
         mImpl = impl;
     }
 
diff --git a/packages/SystemUI/src/com/android/systemui/settings/BrightnessController.java b/packages/SystemUI/src/com/android/systemui/settings/BrightnessController.java
index 1e0a9f1..176676f 100644
--- a/packages/SystemUI/src/com/android/systemui/settings/BrightnessController.java
+++ b/packages/SystemUI/src/com/android/systemui/settings/BrightnessController.java
@@ -152,6 +152,20 @@
     private final Runnable mStartListeningRunnable = new Runnable() {
         @Override
         public void run() {
+            if (mListening) {
+                return;
+            }
+            mListening = true;
+
+            if (mVrManager != null) {
+                try {
+                    mVrManager.registerListener(mVrStateCallbacks);
+                    mIsVrModeEnabled = mVrManager.getVrModeState();
+                } catch (RemoteException e) {
+                    Log.e(TAG, "Failed to register VR mode state listener: ", e);
+                }
+            }
+
             mBrightnessObserver.startObserving();
             mUserTracker.startTracking();
 
@@ -167,6 +181,19 @@
     private final Runnable mStopListeningRunnable = new Runnable() {
         @Override
         public void run() {
+            if (!mListening) {
+                return;
+            }
+            mListening = false;
+
+            if (mVrManager != null) {
+                try {
+                    mVrManager.unregisterListener(mVrStateCallbacks);
+                } catch (RemoteException e) {
+                    Log.e(TAG, "Failed to unregister VR mode state listener: ", e);
+                }
+            }
+
             mBrightnessObserver.stopObserving();
             mUserTracker.stopTracking();
 
@@ -297,39 +324,12 @@
     }
 
     public void registerCallbacks() {
-        if (mListening) {
-            return;
-        }
-
-        if (mVrManager != null) {
-            try {
-                mVrManager.registerListener(mVrStateCallbacks);
-                mIsVrModeEnabled = mVrManager.getVrModeState();
-            } catch (RemoteException e) {
-                Log.e(TAG, "Failed to register VR mode state listener: ", e);
-            }
-        }
-
         mBackgroundHandler.post(mStartListeningRunnable);
-        mListening = true;
     }
 
     /** Unregister all call backs, both to and from the controller */
     public void unregisterCallbacks() {
-        if (!mListening) {
-            return;
-        }
-
-        if (mVrManager != null) {
-            try {
-                mVrManager.unregisterListener(mVrStateCallbacks);
-            } catch (RemoteException e) {
-                Log.e(TAG, "Failed to unregister VR mode state listener: ", e);
-            }
-        }
-
         mBackgroundHandler.post(mStopListeningRunnable);
-        mListening = false;
         mControlValueInitialized = false;
     }
 
diff --git a/packages/SystemUI/src/com/android/systemui/shortcut/ShortcutKeyDispatcher.java b/packages/SystemUI/src/com/android/systemui/shortcut/ShortcutKeyDispatcher.java
index 07675e2..df9791d 100644
--- a/packages/SystemUI/src/com/android/systemui/shortcut/ShortcutKeyDispatcher.java
+++ b/packages/SystemUI/src/com/android/systemui/shortcut/ShortcutKeyDispatcher.java
@@ -19,6 +19,7 @@
 import static android.app.ActivityTaskManager.SPLIT_SCREEN_CREATE_MODE_BOTTOM_OR_RIGHT;
 import static android.app.ActivityTaskManager.SPLIT_SCREEN_CREATE_MODE_TOP_OR_LEFT;
 
+import android.content.Context;
 import android.content.res.Configuration;
 import android.os.RemoteException;
 import android.util.Log;
@@ -52,6 +53,10 @@
     protected final long SC_DOCK_LEFT = META_MASK | KeyEvent.KEYCODE_LEFT_BRACKET;
     protected final long SC_DOCK_RIGHT = META_MASK | KeyEvent.KEYCODE_RIGHT_BRACKET;
 
+    public ShortcutKeyDispatcher(Context context) {
+        super(context);
+    }
+
     /**
      * Registers a shortcut key to window manager.
      * @param shortcutCode packed representation of shortcut key code and meta information
diff --git a/packages/SystemUI/src/com/android/systemui/stackdivider/Divider.java b/packages/SystemUI/src/com/android/systemui/stackdivider/Divider.java
index cd2074f..c8b2b6a 100644
--- a/packages/SystemUI/src/com/android/systemui/stackdivider/Divider.java
+++ b/packages/SystemUI/src/com/android/systemui/stackdivider/Divider.java
@@ -19,6 +19,7 @@
 import static android.content.res.Configuration.ORIENTATION_LANDSCAPE;
 import static android.view.ViewGroup.LayoutParams.MATCH_PARENT;
 
+import android.content.Context;
 import android.content.res.Configuration;
 import android.os.RemoteException;
 import android.util.Log;
@@ -50,6 +51,10 @@
     private boolean mHomeStackResizable = false;
     private ForcedResizableInfoActivityController mForcedResizableController;
 
+    public Divider(Context context) {
+        super(context);
+    }
+
     @Override
     public void start() {
         mWindowManager = new DividerWindowManager(mContext);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/CommandQueue.java b/packages/SystemUI/src/com/android/systemui/statusbar/CommandQueue.java
index 134d4b8..d6a8f90 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/CommandQueue.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/CommandQueue.java
@@ -270,12 +270,13 @@
 
         default void onRotationProposal(int rotation, boolean isValid) { }
 
-        default void showBiometricDialog(Bundle bundle, IBiometricServiceReceiverInternal receiver,
-                int type, boolean requireConfirmation, int userId, String opPackageName) { }
+        default void showAuthenticationDialog(Bundle bundle,
+                IBiometricServiceReceiverInternal receiver, int biometricModality,
+                boolean requireConfirmation, int userId, String opPackageName) { }
         default void onBiometricAuthenticated(boolean authenticated, String failureReason) { }
         default void onBiometricHelp(String message) { }
-        default void onBiometricError(String error) { }
-        default void hideBiometricDialog() { }
+        default void onBiometricError(int errorCode, String error) { }
+        default void hideAuthenticationDialog() { }
 
         /**
          * @see IStatusBar#onDisplayReady(int)
@@ -740,13 +741,13 @@
     }
 
     @Override
-    public void showBiometricDialog(Bundle bundle, IBiometricServiceReceiverInternal receiver,
-            int type, boolean requireConfirmation, int userId, String opPackageName) {
+    public void showAuthenticationDialog(Bundle bundle, IBiometricServiceReceiverInternal receiver,
+            int biometricModality, boolean requireConfirmation, int userId, String opPackageName) {
         synchronized (mLock) {
             SomeArgs args = SomeArgs.obtain();
             args.arg1 = bundle;
             args.arg2 = receiver;
-            args.argi1 = type;
+            args.argi1 = biometricModality;
             args.arg3 = requireConfirmation;
             args.argi2 = userId;
             args.arg4 = opPackageName;
@@ -773,14 +774,14 @@
     }
 
     @Override
-    public void onBiometricError(String error) {
+    public void onBiometricError(int errorCode, String error) {
         synchronized (mLock) {
-            mHandler.obtainMessage(MSG_BIOMETRIC_ERROR, error).sendToTarget();
+            mHandler.obtainMessage(MSG_BIOMETRIC_ERROR, errorCode, 0, error).sendToTarget();
         }
     }
 
     @Override
-    public void hideBiometricDialog() {
+    public void hideAuthenticationDialog() {
         synchronized (mLock) {
             mHandler.obtainMessage(MSG_BIOMETRIC_HIDE).sendToTarget();
         }
@@ -1032,10 +1033,10 @@
                     mHandler.removeMessages(MSG_BIOMETRIC_AUTHENTICATED);
                     SomeArgs someArgs = (SomeArgs) msg.obj;
                     for (int i = 0; i < mCallbacks.size(); i++) {
-                        mCallbacks.get(i).showBiometricDialog(
+                        mCallbacks.get(i).showAuthenticationDialog(
                                 (Bundle) someArgs.arg1,
                                 (IBiometricServiceReceiverInternal) someArgs.arg2,
-                                someArgs.argi1 /* type */,
+                                someArgs.argi1 /* biometricModality */,
                                 (boolean) someArgs.arg3 /* requireConfirmation */,
                                 someArgs.argi2 /* userId */,
                                 (String) someArgs.arg4 /* opPackageName */);
@@ -1060,12 +1061,12 @@
                     break;
                 case MSG_BIOMETRIC_ERROR:
                     for (int i = 0; i < mCallbacks.size(); i++) {
-                        mCallbacks.get(i).onBiometricError((String) msg.obj);
+                        mCallbacks.get(i).onBiometricError(msg.arg1, (String) msg.obj);
                     }
                     break;
                 case MSG_BIOMETRIC_HIDE:
                     for (int i = 0; i < mCallbacks.size(); i++) {
-                        mCallbacks.get(i).hideBiometricDialog();
+                        mCallbacks.get(i).hideAuthenticationDialog();
                     }
                     break;
                 case MSG_SHOW_CHARGING_ANIMATION:
@@ -1100,6 +1101,10 @@
     // Need this class since CommandQueue already extends IStatusBar.Stub, so CommandQueueStart
     // is needed so it can extend SystemUI.
     public static class CommandQueueStart extends SystemUI {
+        public CommandQueueStart(Context context) {
+            super(context);
+        }
+
         @Override
         public void start() {
             putComponent(CommandQueue.class, new CommandQueue(mContext));
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NavigationBarController.java b/packages/SystemUI/src/com/android/systemui/statusbar/NavigationBarController.java
index 16cdfaa..e09e9cd 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/NavigationBarController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/NavigationBarController.java
@@ -152,7 +152,9 @@
             //                    Dependency problem.
             AutoHideController autoHideController = isOnDefaultDisplay
                     ? Dependency.get(AutoHideController.class)
-                    : new AutoHideController(context, mHandler);
+                    : new AutoHideController(context, mHandler,
+                            Dependency.get(NotificationRemoteInputManager.class),
+                            Dependency.get(IWindowManager.class));
             navBar.setAutoHideController(autoHideController);
             navBar.restoreSystemUiVisibilityState();
             mNavigationBars.append(displayId, navBar);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationListener.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationListener.java
index 6c0f90a..c4de2d3 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationListener.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationListener.java
@@ -127,7 +127,7 @@
                         mEntryManager.removeNotification(key, rankingMap, UNDEFINED_DISMISS_REASON);
                     } else {
                         mEntryManager.getNotificationData()
-                                .updateRanking(rankingMap);
+                                .updateRanking(rankingMap, "onNotificationPosted");
                     }
                     return;
                 }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationLockscreenUserManagerImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationLockscreenUserManagerImpl.java
index 4ba1114..6ffea79 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationLockscreenUserManagerImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationLockscreenUserManagerImpl.java
@@ -106,7 +106,7 @@
                     isCurrentProfile(getSendingUserId())) {
                 mUsersAllowingPrivateNotifications.clear();
                 updateLockscreenNotificationSetting();
-                getEntryManager().updateNotifications();
+                getEntryManager().updateNotifications("ACTION_DEVICE_POLICY_MANAGER_STATE_CHANGED");
             }
         }
     };
@@ -124,7 +124,7 @@
                 updatePublicMode();
                 // The filtering needs to happen before the update call below in order to make sure
                 // the presenter has the updated notifications from the new user
-                getEntryManager().getNotificationData().filterAndSort();
+                getEntryManager().getNotificationData().filterAndSort("user switched");
                 mPresenter.onUserSwitched(mCurrentUserId);
 
                 for (UserChangedListener listener : mListeners) {
@@ -205,7 +205,8 @@
                 mUsersAllowingNotifications.clear();
                 // ... and refresh all the notifications
                 updateLockscreenNotificationSetting();
-                getEntryManager().updateNotifications();
+                getEntryManager().updateNotifications("LOCK_SCREEN_SHOW_NOTIFICATIONS,"
+                        + " or LOCK_SCREEN_ALLOW_PRIVATE_NOTIFICATIONS change");
             }
         };
 
@@ -214,7 +215,8 @@
             public void onChange(boolean selfChange) {
                 updateLockscreenNotificationSetting();
                 if (mDeviceProvisionedController.isDeviceProvisioned()) {
-                    getEntryManager().updateNotifications();
+                    getEntryManager().updateNotifications("LOCK_SCREEN_ALLOW_REMOTE_INPUT"
+                            + " or ZEN_MODE change");
                 }
             }
         };
@@ -532,7 +534,7 @@
             setLockscreenPublicMode(isProfilePublic, userId);
             mUsersWithSeperateWorkChallenge.put(userId, needsSeparateChallenge);
         }
-        getEntryManager().updateNotifications();
+        getEntryManager().updateNotifications("NotificationLockscreenUserManager.updatePublicMode");
     }
 
     @Override
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationMediaManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationMediaManager.java
index c50fb3d..3616b54 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationMediaManager.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationMediaManager.java
@@ -361,7 +361,7 @@
         }
 
         if (metaDataChanged) {
-            mEntryManager.updateNotifications();
+            mEntryManager.updateNotifications("NotificationMediaManager - metaDataChanged");
         }
 
         dispatchUpdateMediaMetaData(metaDataChanged, true /* allowEnterAnimation */);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/ActivityLaunchAnimator.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/ActivityLaunchAnimator.java
index 13c6f27..9b31234 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/ActivityLaunchAnimator.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/ActivityLaunchAnimator.java
@@ -38,7 +38,7 @@
 import com.android.systemui.statusbar.notification.stack.NotificationListContainer;
 import com.android.systemui.statusbar.phone.CollapsedStatusBarFragment;
 import com.android.systemui.statusbar.phone.NotificationPanelView;
-import com.android.systemui.statusbar.phone.StatusBarWindowView;
+import com.android.systemui.statusbar.phone.StatusBarWindowViewController;
 
 /**
  * A class that allows activities to be launched in a seamless way where the notification
@@ -55,8 +55,8 @@
     private static final long LAUNCH_TIMEOUT = 500;
     private final NotificationPanelView mNotificationPanel;
     private final NotificationListContainer mNotificationContainer;
-    private final StatusBarWindowView mStatusBarWindow;
     private final float mWindowCornerRadius;
+    private final StatusBarWindowViewController mStatusBarWindowViewController;
     private Callback mCallback;
     private final Runnable mTimeoutRunnable = () -> {
         setAnimationPending(false);
@@ -66,16 +66,17 @@
     private boolean mAnimationRunning;
     private boolean mIsLaunchForActivity;
 
-    public ActivityLaunchAnimator(StatusBarWindowView statusBarWindow,
+    public ActivityLaunchAnimator(
+            StatusBarWindowViewController statusBarWindowViewController,
             Callback callback,
             NotificationPanelView notificationPanel,
             NotificationListContainer container) {
         mNotificationPanel = notificationPanel;
         mNotificationContainer = container;
-        mStatusBarWindow = statusBarWindow;
+        mStatusBarWindowViewController = statusBarWindowViewController;
         mCallback = callback;
         mWindowCornerRadius = ScreenDecorationsUtils
-                .getWindowCornerRadius(statusBarWindow.getResources());
+                .getWindowCornerRadius(mStatusBarWindowViewController.getView().getResources());
     }
 
     public RemoteAnimationAdapter getLaunchAnimation(
@@ -112,11 +113,11 @@
 
     private void setAnimationPending(boolean pending) {
         mAnimationPending = pending;
-        mStatusBarWindow.setExpandAnimationPending(pending);
+        mStatusBarWindowViewController.setExpandAnimationPending(pending);
         if (pending) {
-            mStatusBarWindow.postDelayed(mTimeoutRunnable, LAUNCH_TIMEOUT);
+            mStatusBarWindowViewController.getView().postDelayed(mTimeoutRunnable, LAUNCH_TIMEOUT);
         } else {
-            mStatusBarWindow.removeCallbacks(mTimeoutRunnable);
+            mStatusBarWindowViewController.getView().removeCallbacks(mTimeoutRunnable);
         }
     }
 
@@ -246,7 +247,7 @@
         private void setExpandAnimationRunning(boolean running) {
             mNotificationPanel.setLaunchingNotification(running);
             mSourceNotification.setExpandAnimationRunning(running);
-            mStatusBarWindow.setExpandAnimationRunning(running);
+            mStatusBarWindowViewController.setExpandAnimationRunning(running);
             mNotificationContainer.setExpandingNotification(running ? mSourceNotification : null);
             mAnimationRunning = running;
             if (!running) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/InstantAppNotifier.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/InstantAppNotifier.java
index a5b7fa7..f284f73 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/InstantAppNotifier.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/InstantAppNotifier.java
@@ -31,6 +31,7 @@
 import android.app.PendingIntent;
 import android.app.SynchronousUserSwitchObserver;
 import android.content.ComponentName;
+import android.content.Context;
 import android.content.Intent;
 import android.content.pm.ApplicationInfo;
 import android.content.pm.IPackageManager;
@@ -60,7 +61,7 @@
 
 import java.util.List;
 
-/** The clsss to show notification(s) of instant apps. This may show multiple notifications on
+/** The class to show notification(s) of instant apps. This may show multiple notifications on
  * splitted screen.
  */
 public class InstantAppNotifier extends SystemUI
@@ -74,7 +75,9 @@
     private boolean mDockedStackExists;
     private KeyguardStateController mKeyguardStateController;
 
-    public InstantAppNotifier() {}
+    public InstantAppNotifier(Context context) {
+        super(context);
+    }
 
     @Override
     public void start() {
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 90301c5..01c79b3 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationEntryManager.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationEntryManager.java
@@ -20,7 +20,6 @@
 
 import android.annotation.Nullable;
 import android.app.Notification;
-import android.content.Context;
 import android.service.notification.NotificationListenerService;
 import android.service.notification.NotificationListenerService.Ranking;
 import android.service.notification.StatusBarNotification;
@@ -41,6 +40,8 @@
 import com.android.systemui.statusbar.notification.collection.NotificationData.KeyguardEnvironment;
 import com.android.systemui.statusbar.notification.collection.NotificationEntry;
 import com.android.systemui.statusbar.notification.collection.NotificationRowBinder;
+import com.android.systemui.statusbar.notification.logging.NotifEvent;
+import com.android.systemui.statusbar.notification.logging.NotifLog;
 import com.android.systemui.statusbar.notification.logging.NotificationLogger;
 import com.android.systemui.statusbar.notification.row.NotificationContentInflater;
 import com.android.systemui.statusbar.notification.row.NotificationContentInflater.InflationFlag;
@@ -93,6 +94,7 @@
     private NotificationListenerService.RankingMap mLatestRankingMap;
     @VisibleForTesting
     protected NotificationData mNotificationData;
+    private NotifLog mNotifLog;
 
     @VisibleForTesting
     final ArrayList<NotificationLifetimeExtender> mNotificationLifetimeExtenders
@@ -124,8 +126,9 @@
     }
 
     @Inject
-    public NotificationEntryManager(Context context) {
-        mNotificationData = new NotificationData(context);
+    public NotificationEntryManager(NotificationData notificationData, NotifLog notifLog) {
+        mNotificationData = notificationData;
+        mNotifLog = notifLog;
     }
 
     /** Adds a {@link NotificationEntryListener}. */
@@ -179,7 +182,7 @@
 
     @Override
     public void onReorderingAllowed() {
-        updateNotifications();
+        updateNotifications("reordering is now allowed");
     }
 
     /**
@@ -204,15 +207,19 @@
         return NotificationVisibility.obtain(key, rank, count, true, location);
     }
 
-    private void abortExistingInflation(String key) {
+    private void abortExistingInflation(String key, String reason) {
         if (mPendingNotifications.containsKey(key)) {
             NotificationEntry entry = mPendingNotifications.get(key);
             entry.abortTask();
             mPendingNotifications.remove(key);
+            mNotifLog.log(NotifEvent.INFLATION_ABORTED, entry.sbn(), null,
+                    "PendingNotification aborted. " + reason);
         }
         NotificationEntry addedEntry = mNotificationData.get(key);
         if (addedEntry != null) {
             addedEntry.abortTask();
+            mNotifLog.log(NotifEvent.INFLATION_ABORTED, addedEntry.sbn(),
+                    null, reason);
         }
     }
 
@@ -248,7 +255,7 @@
                 for (NotificationEntryListener listener : mNotificationEntryListeners) {
                     listener.onBeforeNotificationAdded(entry);
                 }
-                updateNotifications();
+                updateNotifications("onAsyncInflationFinished");
                 for (NotificationEntryListener listener : mNotificationEntryListeners) {
                     listener.onNotificationAdded(entry);
                 }
@@ -277,7 +284,8 @@
 
         if (mRemoveInterceptor != null
                 && mRemoveInterceptor.onNotificationRemoveRequested(key, reason)) {
-            // Remove intercepted; skip
+            // Remove intercepted; log and skip
+            mNotifLog.log(NotifEvent.REMOVE_INTERCEPTED);
             return;
         }
 
@@ -292,13 +300,17 @@
                     if (extender.shouldExtendLifetimeForPendingNotification(pendingEntry)) {
                         extendLifetime(pendingEntry, extender);
                         lifetimeExtended = true;
+                        mNotifLog.log(
+                                NotifEvent.LIFETIME_EXTENDED,
+                                pendingEntry.sbn(),
+                                "pendingEntry extendedBy=" + extender.toString());
                     }
                 }
             }
         }
 
         if (!lifetimeExtended) {
-            abortExistingInflation(key);
+            abortExistingInflation(key, "removeNotification");
         }
 
         if (entry != null) {
@@ -311,6 +323,10 @@
                         mLatestRankingMap = ranking;
                         extendLifetime(entry, extender);
                         lifetimeExtended = true;
+                        mNotifLog.log(
+                                NotifEvent.LIFETIME_EXTENDED,
+                                entry.sbn(),
+                                "entry extendedBy=" + extender.toString());
                         break;
                     }
                 }
@@ -330,10 +346,12 @@
                 handleGroupSummaryRemoved(key);
 
                 mNotificationData.remove(key, ranking);
-                updateNotifications();
+                updateNotifications("removeNotificationInternal");
                 Dependency.get(LeakDetector.class).trackGarbage(entry);
                 removedByUser |= entryDismissed;
 
+                mNotifLog.log(NotifEvent.NOTIF_REMOVED, entry.sbn(),
+                        "removedByUser=" + removedByUser);
                 for (NotificationEntryListener listener : mNotificationEntryListeners) {
                     listener.onEntryRemoved(entry, visibility, removedByUser);
                 }
@@ -390,7 +408,7 @@
             Log.d(TAG, "addNotification key=" + key);
         }
 
-        mNotificationData.updateRanking(rankingMap);
+        mNotificationData.updateRanking(rankingMap, "addNotificationInternal");
         Ranking ranking = new Ranking();
         rankingMap.getRanking(key, ranking);
 
@@ -401,9 +419,9 @@
         requireBinder().inflateViews(entry, () -> performRemoveNotification(notification,
                 REASON_CANCEL));
 
-        abortExistingInflation(key);
-
+        abortExistingInflation(key, "addNotification");
         mPendingNotifications.put(key, entry);
+        mNotifLog.log(NotifEvent.NOTIF_ADDED, entry.sbn());
         for (NotificationEntryListener listener : mNotificationEntryListeners) {
             listener.onPendingEntryAdded(entry);
         }
@@ -424,7 +442,7 @@
         if (DEBUG) Log.d(TAG, "updateNotification(" + notification + ")");
 
         final String key = notification.getKey();
-        abortExistingInflation(key);
+        abortExistingInflation(key, "updateNotification");
         NotificationEntry entry = mNotificationData.get(key);
         if (entry == null) {
             return;
@@ -434,15 +452,15 @@
         // to keep its lifetime extended.
         cancelLifetimeExtension(entry);
 
-        mNotificationData.update(entry, ranking, notification);
-
+        mNotificationData.update(entry, ranking, notification, "updateNotificationInternal");
+        mNotifLog.log(NotifEvent.NOTIF_UPDATED, entry.sbn(), entry.ranking());
         for (NotificationEntryListener listener : mNotificationEntryListeners) {
             listener.onPreEntryUpdated(entry);
         }
 
         requireBinder().inflateViews(entry, () -> performRemoveNotification(notification,
                 REASON_CANCEL));
-        updateNotifications();
+        updateNotifications("updateNotificationInternal");
 
         if (DEBUG) {
             // Is this for you?
@@ -466,8 +484,12 @@
         }
     }
 
-    public void updateNotifications() {
-        mNotificationData.filterAndSort();
+    /**
+     * Update the notifications
+     * @param reason why the notifications are updating
+     */
+    public void updateNotifications(String reason) {
+        mNotificationData.filterAndSort(reason);
         if (mPresenter != null) {
             mPresenter.updateNotificationViews();
         }
@@ -490,7 +512,7 @@
         }
 
         // Populate notification entries from the new rankings.
-        mNotificationData.updateRanking(rankingMap);
+        mNotificationData.updateRanking(rankingMap, "updateNotificationRanking");
         updateRankingOfPendingNotifications(rankingMap);
 
         // By comparing the old and new UI adjustments, reinflate the view accordingly.
@@ -502,7 +524,7 @@
                     NotificationUiAdjustment.extractFromNotificationEntry(entry));
         }
 
-        updateNotifications();
+        updateNotifications("updateNotificationRanking");
 
         for (NotificationEntryListener listener : mNotificationEntryListeners) {
             listener.onNotificationRankingUpdated(rankingMap);
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 769cbb7..970cbf9 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationListController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationListController.java
@@ -81,7 +81,7 @@
             new DeviceProvisionedListener() {
                 @Override
                 public void onDeviceProvisionedChanged() {
-                    mEntryManager.updateNotifications();
+                    mEntryManager.updateNotifications("device provisioned changed");
                 }
             };
 
@@ -106,7 +106,7 @@
         if (foregroundKey != null) {
             mEntryManager
                     .getNotificationData().updateAppOp(appOp, uid, pkg, foregroundKey, showIcon);
-            mEntryManager.updateNotifications();
+            mEntryManager.updateNotifications("app opp changed pkg=" + pkg);
         }
     }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationSectionsFeatureManager.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationSectionsFeatureManager.kt
new file mode 100644
index 0000000..480cb78
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationSectionsFeatureManager.kt
@@ -0,0 +1,73 @@
+/*
+ * 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.content.Context
+import android.provider.DeviceConfig
+
+import com.android.internal.annotations.VisibleForTesting
+import com.android.internal.config.sysui.SystemUiDeviceConfigFlags.NOTIFICATIONS_USE_PEOPLE_FILTERING
+import com.android.systemui.statusbar.notification.stack.NotificationSectionsManager.BUCKET_ALERTING
+import com.android.systemui.statusbar.notification.stack.NotificationSectionsManager.BUCKET_PEOPLE
+import com.android.systemui.statusbar.notification.stack.NotificationSectionsManager.BUCKET_SILENT
+import com.android.systemui.util.DeviceConfigProxy
+
+import javax.inject.Inject
+
+private var sUsePeopleFiltering: Boolean? = null
+
+/**
+ * Feature controller for the NOTIFICATIONS_USE_PEOPLE_FILTERING config.
+ */
+class NotificationSectionsFeatureManager @Inject constructor(
+    val proxy: DeviceConfigProxy,
+    val context: Context
+) {
+
+    fun isFilteringEnabled(): Boolean {
+        return usePeopleFiltering(proxy)
+    }
+
+    fun getNotificationBuckets(): IntArray {
+        return when {
+            isFilteringEnabled() ->
+                intArrayOf(BUCKET_PEOPLE, BUCKET_ALERTING, BUCKET_SILENT)
+            NotificationUtils.useNewInterruptionModel(context) ->
+                intArrayOf(BUCKET_ALERTING, BUCKET_SILENT)
+            else ->
+                intArrayOf(BUCKET_ALERTING)
+        }
+    }
+
+    fun getNumberOfBuckets(): Int {
+        return getNotificationBuckets().size
+    }
+
+    @VisibleForTesting
+    fun clearCache() {
+        sUsePeopleFiltering = null
+    }
+}
+
+private fun usePeopleFiltering(proxy: DeviceConfigProxy): Boolean {
+    if (sUsePeopleFiltering == null) {
+        sUsePeopleFiltering = proxy.getBoolean(
+                DeviceConfig.NAMESPACE_SYSTEMUI, NOTIFICATIONS_USE_PEOPLE_FILTERING, false)
+    }
+
+    return sUsePeopleFiltering!!
+}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationUtils.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationUtils.java
index dfbbf98..1af47dd 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationUtils.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationUtils.java
@@ -36,7 +36,6 @@
     private static final int[] sLocationOffset = new int[2];
 
     @Nullable private static Boolean sUseNewInterruptionModel = null;
-    @Nullable private static Boolean sUsePeopleFiltering = null;
 
     public static boolean isGrayscale(ImageView v, ContrastColorUtil colorUtil) {
         Object isGrayscale = v.getTag(R.id.icon_is_grayscale);
@@ -88,17 +87,4 @@
         }
         return sUseNewInterruptionModel;
     }
-
-    /**
-     * Caches and returns the value of the people filtering setting. Cannot change except through
-     * process restarts.
-     */
-    public static boolean usePeopleFiltering(Context context) {
-        if (sUsePeopleFiltering == null) {
-            sUsePeopleFiltering = context.getResources().getBoolean(
-                    R.bool.config_usePeopleFiltering);
-        }
-
-        return sUsePeopleFiltering;
-    }
 }
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 aacb2dd..a98fa66 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
@@ -24,7 +24,6 @@
 import android.app.NotificationChannel;
 import android.app.NotificationManager;
 import android.app.Person;
-import android.content.Context;
 import android.service.notification.NotificationListenerService.Ranking;
 import android.service.notification.NotificationListenerService.RankingMap;
 import android.service.notification.SnoozeCriterion;
@@ -35,7 +34,9 @@
 import com.android.systemui.Dependency;
 import com.android.systemui.statusbar.NotificationMediaManager;
 import com.android.systemui.statusbar.notification.NotificationFilter;
-import com.android.systemui.statusbar.notification.NotificationUtils;
+import com.android.systemui.statusbar.notification.NotificationSectionsFeatureManager;
+import com.android.systemui.statusbar.notification.logging.NotifEvent;
+import com.android.systemui.statusbar.notification.logging.NotifLog;
 import com.android.systemui.statusbar.phone.NotificationGroupManager;
 import com.android.systemui.statusbar.policy.HeadsUpManager;
 
@@ -46,6 +47,8 @@
 import java.util.List;
 import java.util.Objects;
 
+import javax.inject.Inject;
+
 /**
  * The list of currently displaying notifications.
  */
@@ -72,9 +75,13 @@
     private RankingMap mRankingMap;
     private final Ranking mTmpRanking = new Ranking();
     private final boolean mUsePeopleFiltering;
+    private final NotifLog mNotifLog;
 
-    public NotificationData(Context context) {
-        mUsePeopleFiltering = NotificationUtils.usePeopleFiltering(context);
+    @Inject
+    public NotificationData(NotificationSectionsFeatureManager sectionsFeatureManager,
+            NotifLog notifLog) {
+        mUsePeopleFiltering = sectionsFeatureManager.isFilteringEnabled();
+        mNotifLog = notifLog;
     }
 
     public void setHeadsUpManager(HeadsUpManager headsUpManager) {
@@ -177,7 +184,7 @@
         }
         mGroupManager.onEntryAdded(entry);
 
-        updateRankingAndSort(mRankingMap);
+        updateRankingAndSort(mRankingMap, "addEntry=" + entry.sbn());
     }
 
     public NotificationEntry remove(String key, RankingMap ranking) {
@@ -187,7 +194,7 @@
         }
         if (removed == null) return null;
         mGroupManager.onEntryRemoved(removed);
-        updateRankingAndSort(ranking);
+        updateRankingAndSort(ranking, "removeEntry=" + removed.sbn());
         return removed;
     }
 
@@ -195,15 +202,19 @@
     public void update(
             NotificationEntry entry,
             RankingMap ranking,
-            StatusBarNotification notification) {
-        updateRanking(ranking);
+            StatusBarNotification notification,
+            String reason) {
+        updateRanking(ranking, reason);
         final StatusBarNotification oldNotification = entry.notification;
         entry.setNotification(notification);
         mGroupManager.onEntryUpdated(entry, oldNotification);
     }
 
-    public void updateRanking(RankingMap ranking) {
-        updateRankingAndSort(ranking);
+    /**
+     * Update ranking and trigger a re-sort
+     */
+    public void updateRanking(RankingMap ranking, String reason) {
+        updateRankingAndSort(ranking, reason);
     }
 
     public void updateAppOp(int appOp, int uid, String pkg, String key, boolean showIcon) {
@@ -350,7 +361,7 @@
         return false;
     }
 
-    private void updateRankingAndSort(RankingMap rankingMap) {
+    private void updateRankingAndSort(RankingMap rankingMap, String reason) {
         if (rankingMap != null) {
             mRankingMap = rankingMap;
             synchronized (mEntries) {
@@ -373,7 +384,7 @@
                 }
             }
         }
-        filterAndSort();
+        filterAndSort(reason);
     }
 
     /**
@@ -391,7 +402,11 @@
 
     // TODO: This should not be public. Instead the Environment should notify this class when
     // anything changed, and this class should call back the UI so it updates itself.
-    public void filterAndSort() {
+    /**
+     * Filters and sorts the list of notification entries
+     */
+    public void filterAndSort(String reason) {
+        mNotifLog.log(NotifEvent.FILTER_AND_SORT, reason);
         mSortedAndFiltered.clear();
 
         synchronized (mEntries) {
@@ -483,19 +498,6 @@
     }
 
     /**
-     * Get the current set of buckets for notification entries, as defined here
-     */
-    public static int[] getNotificationBuckets(Context context) {
-        if (NotificationUtils.usePeopleFiltering(context)) {
-            return new int[]{BUCKET_PEOPLE, BUCKET_ALERTING, BUCKET_SILENT};
-        } else if (NotificationUtils.useNewInterruptionModel(context)) {
-            return new int[]{BUCKET_ALERTING, BUCKET_SILENT};
-        } else {
-            return new int[]{BUCKET_ALERTING};
-        }
-    }
-
-    /**
      * Provides access to keyguard state and user settings dependent data.
      */
     public interface KeyguardEnvironment {
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 60cf995..e5571b6 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
@@ -41,6 +41,8 @@
 import com.android.systemui.statusbar.notification.InflationException;
 import com.android.systemui.statusbar.notification.NotificationClicker;
 import com.android.systemui.statusbar.notification.NotificationInterruptionStateProvider;
+import com.android.systemui.statusbar.notification.logging.NotifEvent;
+import com.android.systemui.statusbar.notification.logging.NotifLog;
 import com.android.systemui.statusbar.notification.logging.NotificationLogger;
 import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow;
 import com.android.systemui.statusbar.notification.row.NotificationContentInflater;
@@ -72,6 +74,7 @@
     private final boolean mAllowLongPress;
     private final KeyguardBypassController mKeyguardBypassController;
     private final StatusBarStateController mStatusBarStateController;
+    private final NotifLog mNotifLog;
 
     private NotificationRemoteInputManager mRemoteInputManager;
     private NotificationPresenter mPresenter;
@@ -85,12 +88,14 @@
 
     public NotificationRowBinderImpl(Context context, boolean allowLongPress,
             KeyguardBypassController keyguardBypassController,
-            StatusBarStateController statusBarStateController) {
+            StatusBarStateController statusBarStateController,
+            NotifLog notifLog) {
         mContext = context;
         mMessagingUtil = new NotificationMessagingUtil(context);
         mAllowLongPress = allowLongPress;
         mKeyguardBypassController = keyguardBypassController;
         mStatusBarStateController = statusBarStateController;
+        mNotifLog = notifLog;
     }
 
     private NotificationRemoteInputManager getRemoteInputManager() {
@@ -143,6 +148,7 @@
                     row -> {
                         bindRow(entry, pmUser, sbn, row, onDismissRunnable);
                         updateNotification(entry, pmUser, sbn, row);
+                        mNotifLog.log(NotifEvent.INFLATED, sbn);
                     });
         }
     }
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 2396d28..7703cbd 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
@@ -30,9 +30,9 @@
  * and triaging purposes.
  */
 public class NotifEvent extends RichEvent {
-    public static final int TOTAL_EVENT_TYPES = 8;
-    private StatusBarNotification mSbn;
-    private Ranking mRanking;
+    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,9 +44,20 @@
     public NotifEvent(int logLevel, int type, String reason, StatusBarNotification sbn,
             Ranking ranking) {
         super(logLevel, type, reason);
-        mSbn = sbn.clone();
-        mRanking = new Ranking();
-        mRanking.populate(ranking);
+
+        if (sbn != null) {
+            mSbn = sbn.cloneLight();
+        } else {
+            mSbn = null;
+        }
+
+        if (ranking != null) {
+            mRanking = new Ranking();
+            mRanking.populate(ranking);
+        } else {
+            mRanking = null;
+        }
+
         mMessage += getExtraInfo();
     }
 
@@ -76,11 +87,14 @@
                 "NotifAdded",
                 "NotifRemoved",
                 "NotifUpdated",
-                "HeadsUpStarted",
-                "HeadsUpEnded",
                 "Filter",
                 "Sort",
+                "FilterAndSort",
                 "NotifVisibilityChanged",
+                "LifetimeExtended",
+                "RemoveIntercepted",
+                "InflationAborted",
+                "Inflated"
         };
 
         if (events.length != TOTAL_EVENT_TYPES) {
@@ -135,8 +149,19 @@
         }
     }
 
-    @IntDef({NOTIF_ADDED, NOTIF_REMOVED, NOTIF_UPDATED, HEADS_UP_STARTED, HEADS_UP_ENDED, FILTER,
-            SORT, NOTIF_VISIBILITY_CHANGED})
+    @IntDef({NOTIF_ADDED,
+            NOTIF_REMOVED,
+            NOTIF_UPDATED,
+            FILTER,
+            SORT,
+            FILTER_AND_SORT,
+            NOTIF_VISIBILITY_CHANGED,
+            LIFETIME_EXTENDED,
+            REMOVE_INTERCEPTED,
+            INFLATION_ABORTED,
+            INFLATED
+    })
+
     /**
      * Types of NotifEvents
      */
@@ -145,9 +170,13 @@
     public static final int NOTIF_ADDED = 0;
     public static final int NOTIF_REMOVED = 1;
     public static final int NOTIF_UPDATED = 2;
-    public static final int HEADS_UP_STARTED = 3;
-    public static final int HEADS_UP_ENDED = 4;
-    public static final int FILTER = 5;
-    public static final int SORT = 6;
-    public static final int NOTIF_VISIBILITY_CHANGED = 7;
+    public static final int FILTER = 3;
+    public static final int SORT = 4;
+    public static final int FILTER_AND_SORT = 5;
+    public static final int NOTIF_VISIBILITY_CHANGED = 6;
+    public static final int LIFETIME_EXTENDED = 7;
+    // unable to remove notif - removal intercepted by {@link NotificationRemoveInterceptor}
+    public static final int REMOVE_INTERCEPTED = 8;
+    public static final int INFLATION_ABORTED = 9;
+    public static final int INFLATED = 10;
 }
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 d42cd82..8466d2e8 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
@@ -82,6 +82,14 @@
     }
 
     /**
+     * Logs a {@link NotifEvent} with a notification
+     * @return true if successfully logged, else false
+     */
+    public boolean log(@NotifEvent.EventType int eventType, StatusBarNotification sbn, String msg) {
+        return log(eventType, sbn, null, msg);
+    }
+
+    /**
      * Logs a {@link NotifEvent} with a ranking
      * @return true if successfully logged, else false
      */
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 9f4b026..924a347 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
@@ -1447,6 +1447,7 @@
         }
         setDismissed(fromAccessibility);
         if (mEntry.isClearable()) {
+            // TODO: beverlyt, log dismissal
             // TODO: track dismiss sentiment
             if (mOnDismissRunnable != null) {
                 mOnDismissRunnable.run();
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationBlockingHelperManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationBlockingHelperManager.java
index 73093c6..37f63c9 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationBlockingHelperManager.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationBlockingHelperManager.java
@@ -139,7 +139,8 @@
 
             mBlockingHelperRow.setBlockingHelperShowing(false);
             if (mBlockingHelperRow.isAttachedToWindow()) {
-                Dependency.get(NotificationEntryManager.class).updateNotifications();
+                Dependency.get(NotificationEntryManager.class).updateNotifications(
+                        "dismissCurrentBlockingHelper");
             }
             mBlockingHelperRow = null;
             return true;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationGuts.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationGuts.java
index 4700baa..18d436f 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationGuts.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationGuts.java
@@ -421,7 +421,7 @@
     }
 
     /** Listener for animations executed in {@link #animateClose(int, int, boolean)}. */
-    private static class AnimateCloseListener extends AnimatorListenerAdapter {
+    private class AnimateCloseListener extends AnimatorListenerAdapter {
         final View mView;
         private final GutsContent mGutsContent;
 
@@ -433,8 +433,10 @@
         @Override
         public void onAnimationEnd(Animator animation) {
             super.onAnimationEnd(animation);
-            mView.setVisibility(View.GONE);
-            mGutsContent.onFinishedClosing();
+            if (!isExposed()) {
+                mView.setVisibility(View.GONE);
+                mGutsContent.onFinishedClosing();
+            }
         }
     }
 }
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 9d0dd6b..2b7deec 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
@@ -100,6 +100,7 @@
     protected String mKeyToRemoveOnGutsClosed;
 
     private StatusBar mStatusBar;
+    private Runnable mOpenRunnable;
 
     @Inject
     public NotificationGutsManager(
@@ -343,6 +344,7 @@
     public void closeAndSaveGuts(boolean removeLeavebehinds, boolean force, boolean removeControls,
             int x, int y, boolean resetMenu) {
         if (mNotificationGutsExposed != null) {
+            mNotificationGutsExposed.removeCallbacks(mOpenRunnable);
             mNotificationGutsExposed.closeControls(removeLeavebehinds, removeControls, x, y, force);
         }
         if (resetMenu) {
@@ -445,7 +447,7 @@
         // ensure that it's laid but not visible until actually laid out
         guts.setVisibility(View.INVISIBLE);
         // Post to ensure the the guts are properly laid out.
-        guts.post(new Runnable() {
+        mOpenRunnable = new Runnable() {
             @Override
             public void run() {
                 if (row.getWindowToken() == null) {
@@ -470,7 +472,8 @@
                 mListContainer.onHeightChanged(row, true /* needsAnimation */);
                 mGutsMenuItem = menuItem;
             }
-        });
+        };
+        guts.post(mOpenRunnable);
         return true;
     }
 
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationRoundnessManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationRoundnessManager.java
index ec0c634..b4f7b59 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationRoundnessManager.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationRoundnessManager.java
@@ -16,10 +16,9 @@
 
 package com.android.systemui.statusbar.notification.stack;
 
-import android.content.Context;
 import android.util.MathUtils;
 
-import com.android.systemui.statusbar.notification.collection.NotificationData;
+import com.android.systemui.statusbar.notification.NotificationSectionsFeatureManager;
 import com.android.systemui.statusbar.notification.collection.NotificationEntry;
 import com.android.systemui.statusbar.notification.row.ActivatableNotificationView;
 import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow;
@@ -52,8 +51,8 @@
     @Inject
     NotificationRoundnessManager(
             KeyguardBypassController keyguardBypassController,
-            Context context) {
-        int numberOfSections = NotificationData.getNotificationBuckets(context).length;
+            NotificationSectionsFeatureManager sectionsFeatureManager) {
+        int numberOfSections = sectionsFeatureManager.getNumberOfBuckets();
         mFirstInSectionViews = new ActivatableNotificationView[numberOfSections];
         mLastInSectionViews = new ActivatableNotificationView[numberOfSections];
         mTmpFirstInSectionViews = new ActivatableNotificationView[numberOfSections];
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 a67018e..9817825 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
@@ -109,11 +109,11 @@
 import com.android.systemui.statusbar.notification.FakeShadowView;
 import com.android.systemui.statusbar.notification.NotificationEntryListener;
 import com.android.systemui.statusbar.notification.NotificationEntryManager;
+import com.android.systemui.statusbar.notification.NotificationSectionsFeatureManager;
 import com.android.systemui.statusbar.notification.NotificationUtils;
 import com.android.systemui.statusbar.notification.ShadeViewRefactor;
 import com.android.systemui.statusbar.notification.ShadeViewRefactor.RefactorComponent;
 import com.android.systemui.statusbar.notification.VisualStabilityManager;
-import com.android.systemui.statusbar.notification.collection.NotificationData;
 import com.android.systemui.statusbar.notification.collection.NotificationEntry;
 import com.android.systemui.statusbar.notification.logging.NotificationLogger;
 import com.android.systemui.statusbar.notification.row.ActivatableNotificationView;
@@ -473,8 +473,7 @@
     private int mHeadsUpInset;
     private HeadsUpAppearanceController mHeadsUpAppearanceController;
     private NotificationIconAreaController mIconAreaController;
-    private final NotificationLockscreenUserManager mLockscreenUserManager =
-            Dependency.get(NotificationLockscreenUserManager.class);
+    private final NotificationLockscreenUserManager mLockscreenUserManager;
     private final Rect mTmpRect = new Rect();
     private final NotificationEntryManager mEntryManager =
             Dependency.get(NotificationEntryManager.class);
@@ -497,8 +496,7 @@
     private NotificationPanelView mNotificationPanel;
     private final ShadeController mShadeController = Dependency.get(ShadeController.class);
 
-    private final NotificationGutsManager
-            mNotificationGutsManager = Dependency.get(NotificationGutsManager.class);
+    private final NotificationGutsManager mNotificationGutsManager;
     private final NotificationSectionsManager mSectionsManager;
     private boolean mAnimateBottomOnLayout;
     private float mLastSentAppear;
@@ -517,7 +515,10 @@
             StatusBarStateController statusBarStateController,
             HeadsUpManagerPhone headsUpManager,
             KeyguardBypassController keyguardBypassController,
-            FalsingManager falsingManager) {
+            FalsingManager falsingManager,
+            NotificationLockscreenUserManager notificationLockscreenUserManager,
+            NotificationGutsManager notificationGutsManager,
+            NotificationSectionsFeatureManager sectionsFeatureManager) {
         super(context, attrs, 0, 0);
         Resources res = getResources();
 
@@ -525,13 +526,15 @@
 
         mRoundnessManager = notificationRoundnessManager;
 
+        mLockscreenUserManager = notificationLockscreenUserManager;
+        mNotificationGutsManager = notificationGutsManager;
         mHeadsUpManager = headsUpManager;
         mHeadsUpManager.addListener(mRoundnessManager);
         mHeadsUpManager.setAnimationStateHandler(this::setHeadsUpGoingAwayAnimationsAllowed);
         mKeyguardBypassController = keyguardBypassController;
         mFalsingManager = falsingManager;
 
-        int[] buckets = NotificationData.getNotificationBuckets(context);
+        int[] buckets = sectionsFeatureManager.getNotificationBuckets();
         mSectionsManager =
                 new NotificationSectionsManager(
                         this,
@@ -5332,7 +5335,7 @@
         requestChildrenUpdate();
         onUpdateRowStates();
 
-        mEntryManager.updateNotifications();
+        mEntryManager.updateNotifications("StatusBar state changed");
         updateVisibility();
     }
 
@@ -6491,12 +6494,12 @@
 
         @Override
         public void onGroupCreatedFromChildren(NotificationGroupManager.NotificationGroup group) {
-            mStatusBar.requestNotificationUpdate();
+            mStatusBar.requestNotificationUpdate("onGroupCreatedFromChildren");
         }
 
         @Override
         public void onGroupsChanged() {
-            mStatusBar.requestNotificationUpdate();
+            mStatusBar.requestNotificationUpdate("onGroupsChanged");
         }
     };
 
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/AutoHideController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/AutoHideController.java
index 5912cd7..175d072 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/AutoHideController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/AutoHideController.java
@@ -29,7 +29,6 @@
 import android.view.View;
 
 import com.android.internal.annotations.VisibleForTesting;
-import com.android.systemui.Dependency;
 import com.android.systemui.SysUiServiceProvider;
 import com.android.systemui.statusbar.CommandQueue;
 import com.android.systemui.statusbar.NotificationRemoteInputManager;
@@ -68,12 +67,14 @@
     };
 
     @Inject
-    public AutoHideController(Context context, @Named(MAIN_HANDLER_NAME) Handler handler) {
+    public AutoHideController(Context context, @Named(MAIN_HANDLER_NAME) Handler handler,
+            NotificationRemoteInputManager notificationRemoteInputManager,
+            IWindowManager iWindowManager) {
         mCommandQueue = SysUiServiceProvider.getComponent(context, CommandQueue.class);
         mCommandQueue.addCallback(this);
         mHandler = handler;
-        mRemoteInputManager = Dependency.get(NotificationRemoteInputManager.class);
-        mWindowManagerService = Dependency.get(IWindowManager.class);
+        mRemoteInputManager = notificationRemoteInputManager;
+        mWindowManagerService = iWindowManager;
 
         mDisplayId = context.getDisplayId();
     }
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 4cd3ad2..ca7c227 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/EdgeBackGestureHandler.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/EdgeBackGestureHandler.java
@@ -16,6 +16,8 @@
 package com.android.systemui.statusbar.phone;
 
 import static android.view.Display.INVALID_DISPLAY;
+import static android.view.View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY;
+import static android.view.View.NAVIGATION_BAR_TRANSIENT;
 
 import android.content.Context;
 import android.content.res.Resources;
@@ -131,6 +133,7 @@
     private boolean mIsAttached;
     private boolean mIsGesturalModeEnabled;
     private boolean mIsEnabled;
+    private boolean mIsInTransientImmersiveStickyState;
 
     private InputMonitor mInputMonitor;
     private InputEventReceiver mInputEventReceiver;
@@ -195,6 +198,12 @@
         updateCurrentUserResources(currentUserContext.getResources());
     }
 
+    public void onSystemUiVisibilityChanged(int systemUiVisibility) {
+        mIsInTransientImmersiveStickyState =
+                (systemUiVisibility & SYSTEM_UI_FLAG_IMMERSIVE_STICKY) != 0
+                && (systemUiVisibility & NAVIGATION_BAR_TRANSIENT) != 0;
+    }
+
     private void disposeInputChannel() {
         if (mInputEventReceiver != null) {
             mInputEventReceiver.dispose();
@@ -296,13 +305,21 @@
     }
 
     private boolean isWithinTouchRegion(int x, int y) {
+        // Disallow if over the IME
         if (y > (mDisplaySize.y - Math.max(mImeHeight, mNavBarHeight))) {
             return false;
         }
 
+        // Disallow if too far from the edge
         if (x > mEdgeWidth + mLeftInset && x < (mDisplaySize.x - mEdgeWidth - mRightInset)) {
             return false;
         }
+
+        // Always allow if the user is in a transient sticky immersive state
+        if (mIsInTransientImmersiveStickyState) {
+            return true;
+        }
+
         boolean isInExcludedRegion = mExcludeRegion.contains(x, y);
         if (isInExcludedRegion) {
             mOverviewProxyService.notifyBackAction(false /* completed */, -1, -1,
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/HeadsUpAppearanceController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/HeadsUpAppearanceController.java
index da62d9b..ce96005 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/HeadsUpAppearanceController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/HeadsUpAppearanceController.java
@@ -98,9 +98,10 @@
             View statusbarView,
             SysuiStatusBarStateController statusBarStateController,
             KeyguardBypassController keyguardBypassController,
+            KeyguardStateController keyguardStateController,
             NotificationWakeUpCoordinator wakeUpCoordinator) {
         this(notificationIconAreaController, headsUpManager, statusBarStateController,
-                keyguardBypassController, wakeUpCoordinator,
+                keyguardBypassController, wakeUpCoordinator, keyguardStateController,
                 statusbarView.findViewById(R.id.heads_up_status_bar_view),
                 statusbarView.findViewById(R.id.notification_stack_scroller),
                 statusbarView.findViewById(R.id.notification_panel),
@@ -116,6 +117,7 @@
             StatusBarStateController stateController,
             KeyguardBypassController bypassController,
             NotificationWakeUpCoordinator wakeUpCoordinator,
+            KeyguardStateController keyguardStateController,
             HeadsUpStatusBarView headsUpStatusBarView,
             NotificationStackScrollLayout stackScroller,
             NotificationPanelView panelView,
@@ -160,7 +162,7 @@
         mWakeUpCoordinator = wakeUpCoordinator;
         wakeUpCoordinator.addListener(this);
         mCommandQueue = getComponent(headsUpStatusBarView.getContext(), CommandQueue.class);
-        mKeyguardStateController = Dependency.get(KeyguardStateController.class);
+        mKeyguardStateController = keyguardStateController;
     }
 
 
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBottomAreaView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBottomAreaView.java
index 68eca8d6..d95d2b7 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBottomAreaView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBottomAreaView.java
@@ -117,6 +117,9 @@
     private static final int DOZE_ANIMATION_STAGGER_DELAY = 48;
     private static final int DOZE_ANIMATION_ELEMENT_DURATION = 250;
 
+    private final boolean mShowLeftAffordance;
+    private final boolean mShowCameraAffordance;
+
     private KeyguardAffordanceView mRightAffordanceView;
     private KeyguardAffordanceView mLeftAffordanceView;
     private ViewGroup mIndicationArea;
@@ -129,7 +132,6 @@
 
     private ActivityStarter mActivityStarter;
     private KeyguardStateController mKeyguardStateController;
-    private LockPatternUtils mLockPatternUtils;
     private FlashlightController mFlashlightController;
     private PreviewInflater mPreviewInflater;
     private AccessibilityController mAccessibilityController;
@@ -184,6 +186,9 @@
     public KeyguardBottomAreaView(Context context, AttributeSet attrs, int defStyleAttr,
             int defStyleRes) {
         super(context, attrs, defStyleAttr, defStyleRes);
+        mShowLeftAffordance = getResources().getBoolean(R.bool.config_keyguardShowLeftAffordance);
+        mShowCameraAffordance = getResources()
+                .getBoolean(R.bool.config_keyguardShowCameraAffordance);
     }
 
     private AccessibilityDelegate mAccessibilityDelegate = new AccessibilityDelegate() {
@@ -225,7 +230,6 @@
     @Override
     protected void onFinishInflate() {
         super.onFinishInflate();
-        mLockPatternUtils = new LockPatternUtils(mContext);
         mPreviewInflater = new PreviewInflater(mContext, new LockPatternUtils(mContext),
                 new ActivityIntentHelper(mContext));
         mPreviewContainer = findViewById(R.id.preview_container);
@@ -371,8 +375,8 @@
             // Things are not set up yet; reply hazy, ask again later
             return;
         }
-        mRightAffordanceView.setVisibility(!mDozing && mRightButton.getIcon().isVisible
-                ? View.VISIBLE : View.GONE);
+        mRightAffordanceView.setVisibility(!mDozing && mShowCameraAffordance
+                && mRightButton.getIcon().isVisible ? View.VISIBLE : View.GONE);
     }
 
     /**
@@ -384,8 +388,12 @@
     }
 
     private void updateLeftAffordanceIcon() {
+        if (!mShowLeftAffordance || mDozing) {
+            mLeftAffordanceView.setVisibility(GONE);
+            return;
+        }
         IconState state = mLeftButton.getIcon();
-        mLeftAffordanceView.setVisibility(!mDozing && state.isVisible ? View.VISIBLE : View.GONE);
+        mLeftAffordanceView.setVisibility(state.isVisible ? View.VISIBLE : View.GONE);
         if (state.drawable != mLeftAffordanceView.getDrawable()
                 || state.tint != mLeftAffordanceView.shouldTint()) {
             mLeftAffordanceView.setImageDrawable(state.drawable, state.tint);
@@ -767,10 +775,8 @@
         @Override
         public IconState getIcon() {
             mLeftIsVoiceAssist = canLaunchVoiceAssist();
-            final boolean showAffordance =
-                    getResources().getBoolean(R.bool.config_keyguardShowLeftAffordance);
             if (mLeftIsVoiceAssist) {
-                mIconState.isVisible = mUserSetupComplete && showAffordance;
+                mIconState.isVisible = mUserSetupComplete && mShowLeftAffordance;
                 if (mLeftAssistIcon == null) {
                     mIconState.drawable = mContext.getDrawable(R.drawable.ic_mic_26dp);
                 } else {
@@ -779,7 +785,8 @@
                 mIconState.contentDescription = mContext.getString(
                         R.string.accessibility_voice_assist_button);
             } else {
-                mIconState.isVisible = mUserSetupComplete && showAffordance && isPhoneVisible();
+                mIconState.isVisible = mUserSetupComplete && mShowLeftAffordance
+                        && isPhoneVisible();
                 mIconState.drawable = mContext.getDrawable(
                         com.android.internal.R.drawable.ic_phone);
                 mIconState.contentDescription = mContext.getString(
@@ -802,7 +809,7 @@
         public IconState getIcon() {
             boolean isCameraDisabled = (mStatusBar != null) && !mStatusBar.isCameraAllowedByAdmin();
             mIconState.isVisible = !isCameraDisabled
-                    && getResources().getBoolean(R.bool.config_keyguardShowCameraAffordance)
+                    && mShowCameraAffordance
                     && mUserSetupComplete
                     && resolveCameraIntent() != null;
             mIconState.drawable = mContext.getDrawable(R.drawable.ic_camera_alt_24dp);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBouncer.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBouncer.java
index c3de843..f34c15c 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBouncer.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBouncer.java
@@ -17,7 +17,6 @@
 package com.android.systemui.statusbar.phone;
 
 import static com.android.keyguard.KeyguardSecurityModel.SecurityMode;
-import static com.android.systemui.DejankUtils.whitelistIpcs;
 import static com.android.systemui.plugins.ActivityStarter.OnDismissAction;
 
 import android.content.Context;
@@ -38,11 +37,13 @@
 
 import com.android.internal.widget.LockPatternUtils;
 import com.android.keyguard.KeyguardHostView;
+import com.android.keyguard.KeyguardSecurityModel;
 import com.android.keyguard.KeyguardSecurityView;
 import com.android.keyguard.KeyguardUpdateMonitor;
 import com.android.keyguard.KeyguardUpdateMonitorCallback;
 import com.android.keyguard.ViewMediatorCallback;
 import com.android.systemui.DejankUtils;
+import com.android.systemui.Dependency;
 import com.android.systemui.R;
 import com.android.systemui.keyguard.DismissCallbackRegistry;
 import com.android.systemui.plugins.FalsingManager;
@@ -461,15 +462,9 @@
      * notifications on Keyguard, like SIM PIN/PUK.
      */
     public boolean needsFullscreenBouncer() {
-        // TODO(b/140059518)
-        return whitelistIpcs(() -> {
-            ensureView();
-            if (mKeyguardView != null) {
-                SecurityMode mode = mKeyguardView.getSecurityMode();
-                return mode == SecurityMode.SimPin || mode == SecurityMode.SimPuk;
-            }
-            return false;
-        });
+        SecurityMode mode = Dependency.get(KeyguardSecurityModel.class).getSecurityMode(
+                KeyguardUpdateMonitor.getCurrentUser());
+        return mode == SecurityMode.SimPin || mode == SecurityMode.SimPuk;
     }
 
     /**
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarFragment.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarFragment.java
index 6e61d7c..38dc5ea 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarFragment.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarFragment.java
@@ -560,6 +560,9 @@
                 }
                 mAutoHideController.touchAutoHide();
             }
+            if (mNavigationBarView != null) {
+                mNavigationBarView.onSystemUiVisibilityChanged(mSystemUiVisibility);
+            }
         }
         mLightBarController.onNavigationVisibilityChanged(
                 vis, mask, nbModeChanged, mNavigationBarMode, navbarColorManagedByIme);
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 a1a47e1..9804f9f 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarView.java
@@ -67,6 +67,7 @@
 import com.android.systemui.Interpolators;
 import com.android.systemui.R;
 import com.android.systemui.SysUiServiceProvider;
+import com.android.systemui.assist.AssistHandleViewController;
 import com.android.systemui.assist.AssistManager;
 import com.android.systemui.model.SysUiState;
 import com.android.systemui.recents.OverviewProxyService;
@@ -75,6 +76,7 @@
 import com.android.systemui.shared.system.ActivityManagerWrapper;
 import com.android.systemui.shared.system.QuickStepContract;
 import com.android.systemui.shared.system.WindowManagerWrapper;
+import com.android.systemui.statusbar.NavigationBarController;
 import com.android.systemui.statusbar.policy.DeadZone;
 import com.android.systemui.statusbar.policy.KeyButtonDrawable;
 
@@ -364,6 +366,10 @@
         return super.onTouchEvent(event);
     }
 
+    void onSystemUiVisibilityChanged(int systemUiVisibility) {
+        mEdgeBackGestureHandler.onSystemUiVisibilityChanged(systemUiVisibility);
+    }
+
     void onBarTransition(int newMode) {
         if (newMode == MODE_OPAQUE) {
             // If the nav bar background is opaque, stop auto tinting since we know the icons are
@@ -1198,6 +1204,19 @@
         // we're passing the insets onto the gesture handler since the back arrow is only
         // conditionally added and doesn't always get all the insets.
         mEdgeBackGestureHandler.setInsets(leftInset, rightInset);
+
+        // this allows assist handle to be drawn outside its bound so that it can align screen
+        // bottom by translating its y position.
+        final boolean shouldClip =
+                !isGesturalMode(mNavBarMode) || insets.getSystemWindowInsetBottom() == 0;
+        setClipChildren(shouldClip);
+        setClipToPadding(shouldClip);
+
+        AssistHandleViewController controller = Dependency.get(NavigationBarController.class)
+                .getAssistHandlerViewController();
+        if (controller != null) {
+            controller.setBottomOffset(insets.getSystemWindowInsetBottom());
+        }
         return super.onApplyWindowInsets(insets);
     }
 
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 cee1d5d..177294b 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java
@@ -89,6 +89,7 @@
 import com.android.systemui.statusbar.PulseExpansionHandler;
 import com.android.systemui.statusbar.RemoteInputController;
 import com.android.systemui.statusbar.StatusBarState;
+import com.android.systemui.statusbar.SysuiStatusBarStateController;
 import com.android.systemui.statusbar.notification.ActivityLaunchAnimator;
 import com.android.systemui.statusbar.notification.AnimatableProperty;
 import com.android.systemui.statusbar.notification.DynamicPrivacyController;
@@ -408,14 +409,11 @@
             .setDuration(200)
             .setAnimationFinishListener(mAnimatorListenerAdapter)
             .setCustomInterpolator(PANEL_ALPHA.getProperty(), Interpolators.ALPHA_IN);
-    private final NotificationEntryManager mEntryManager =
-            Dependency.get(NotificationEntryManager.class);
+    private final NotificationEntryManager mEntryManager;
 
     private final CommandQueue mCommandQueue;
-    private final NotificationLockscreenUserManager mLockscreenUserManager =
-            Dependency.get(NotificationLockscreenUserManager.class);
-    private final ShadeController mShadeController =
-            Dependency.get(ShadeController.class);
+    private final NotificationLockscreenUserManager mLockscreenUserManager;
+    private final ShadeController mShadeController;
     private int mDisplayId;
 
     /**
@@ -461,8 +459,14 @@
             KeyguardBypassController bypassController,
             FalsingManager falsingManager,
             PluginManager pluginManager,
+            ShadeController shadeController,
+            NotificationLockscreenUserManager notificationLockscreenUserManager,
+            NotificationEntryManager notificationEntryManager,
+            KeyguardStateController keyguardStateController,
+            StatusBarStateController statusBarStateController,
             DozeLog dozeLog) {
-        super(context, attrs, falsingManager, dozeLog);
+        super(context, attrs, falsingManager, dozeLog, keyguardStateController,
+                (SysuiStatusBarStateController) statusBarStateController);
         setWillNotDraw(!DEBUG);
         mInjectionInflationController = injectionInflationController;
         mFalsingManager = falsingManager;
@@ -495,6 +499,11 @@
         mBottomAreaShadeAlphaAnimator.setDuration(160);
         mBottomAreaShadeAlphaAnimator.setInterpolator(Interpolators.ALPHA_OUT);
         mPluginManager = pluginManager;
+        mShadeController = shadeController;
+        mLockscreenUserManager = notificationLockscreenUserManager;
+        mEntryManager = notificationEntryManager;
+
+        setBackgroundColor(Color.TRANSPARENT);
     }
 
     /**
@@ -509,9 +518,11 @@
         mKeyguardBottomArea.setStatusBar(mStatusBar);
     }
 
-    @Override
-    protected void onFinishInflate() {
-        super.onFinishInflate();
+    /**
+     * Call after this view has been fully inflated and had its children attached.
+     */
+    public void onChildrenAttached() {
+        loadDimens();
         mKeyguardStatusBar = findViewById(R.id.keyguard_header);
         mKeyguardStatusView = findViewById(R.id.keyguard_status_view);
 
@@ -554,7 +565,7 @@
             }
         });
 
-        Dependency.get(PluginManager.class).addPluginListener(
+        mPluginManager.addPluginListener(
                 new PluginListener<HomeControlsPlugin>() {
 
                     @Override
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelView.java
index 432d636..e8e5e1f 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelView.java
@@ -44,7 +44,6 @@
 import com.android.systemui.R;
 import com.android.systemui.doze.DozeLog;
 import com.android.systemui.plugins.FalsingManager;
-import com.android.systemui.plugins.statusbar.StatusBarStateController;
 import com.android.systemui.statusbar.FlingAnimationUtils;
 import com.android.systemui.statusbar.StatusBarState;
 import com.android.systemui.statusbar.SysuiStatusBarStateController;
@@ -144,10 +143,8 @@
     private boolean mGestureWaitForTouchSlop;
     private boolean mIgnoreXTouchSlop;
     private boolean mExpandLatencyTracking;
-    protected final KeyguardStateController mKeyguardStateController = Dependency.get(
-            KeyguardStateController.class);
-    protected final SysuiStatusBarStateController mStatusBarStateController =
-            (SysuiStatusBarStateController) Dependency.get(StatusBarStateController.class);
+    protected final KeyguardStateController mKeyguardStateController;
+    protected final SysuiStatusBarStateController mStatusBarStateController;
 
     protected void onExpandingFinished() {
         mBar.onExpandingFinished();
@@ -206,8 +203,11 @@
     }
 
     public PanelView(Context context, AttributeSet attrs, FalsingManager falsingManager,
-            DozeLog dozeLog) {
+            DozeLog dozeLog, KeyguardStateController keyguardStateController,
+            SysuiStatusBarStateController statusBarStateController) {
         super(context, attrs);
+        mKeyguardStateController = keyguardStateController;
+        mStatusBarStateController = statusBarStateController;
         mFlingAnimationUtils = new FlingAnimationUtils(context, 0.6f /* maxLengthSeconds */,
                 0.6f /* speedUpFactor */);
         mFlingAnimationUtilsClosing = new FlingAnimationUtils(context, 0.5f /* maxLengthSeconds */,
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 e79f141..9093687 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java
@@ -25,7 +25,6 @@
 import static android.app.StatusBarManager.windowStateToString;
 import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN_OR_SPLIT_SCREEN_SECONDARY;
 
-import static com.android.systemui.DejankUtils.whitelistIpcs;
 import static com.android.systemui.Dependency.ALLOW_NOTIFICATION_LONG_PRESS_NAME;
 import static com.android.systemui.Dependency.BG_HANDLER;
 import static com.android.systemui.Dependency.MAIN_HANDLER;
@@ -211,6 +210,7 @@
 import com.android.systemui.statusbar.notification.VisualStabilityManager;
 import com.android.systemui.statusbar.notification.collection.NotificationEntry;
 import com.android.systemui.statusbar.notification.collection.NotificationRowBinderImpl;
+import com.android.systemui.statusbar.notification.logging.NotifLog;
 import com.android.systemui.statusbar.notification.logging.NotificationLogger;
 import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow;
 import com.android.systemui.statusbar.notification.row.NotificationGutsManager;
@@ -244,9 +244,11 @@
 
 import javax.inject.Inject;
 import javax.inject.Named;
+import javax.inject.Singleton;
 
 import dagger.Subcomponent;
 
+@Singleton
 public class StatusBar extends SystemUI implements DemoMode,
         ActivityStarter, KeyguardStateController.Callback,
         OnHeadsUpChangedListener, CommandQueue.Callbacks, ZenModeController.Callback,
@@ -347,21 +349,20 @@
     private BrightnessMirrorController mBrightnessMirrorController;
     private boolean mBrightnessMirrorVisible;
     protected BiometricUnlockController mBiometricUnlockController;
-    @Inject LightBarController mLightBarController;
+    private final LightBarController mLightBarController;
     protected LockscreenWallpaper mLockscreenWallpaper;
-    @VisibleForTesting
-    @Inject AutoHideController mAutoHideController;
+    private final AutoHideController mAutoHideController;
 
     private int mNaturalBarHeight = -1;
 
     private final Point mCurrentDisplaySize = new Point();
 
+    protected StatusBarWindowViewController mStatusBarWindowViewController;
     protected StatusBarWindowView mStatusBarWindow;
     protected PhoneStatusBarView mStatusBarView;
     private int mStatusBarWindowState = WINDOW_STATE_SHOWING;
     protected StatusBarWindowController mStatusBarWindowController;
-    @VisibleForTesting
-    @Inject KeyguardUpdateMonitor mKeyguardUpdateMonitor;
+    private final KeyguardUpdateMonitor mKeyguardUpdateMonitor;
     @VisibleForTesting
     DozeServiceHost mDozeServiceHost = new DozeServiceHost();
     private boolean mWakeUpComingFromTouch;
@@ -369,38 +370,23 @@
 
     private final Object mQueueLock = new Object();
 
-    @Inject StatusBarIconController mIconController;
-    @Inject
-    DozeLog mDozeLog;
-    @Inject
-    InjectionInflationController mInjectionInflater;
-    @Inject
-    PulseExpansionHandler mPulseExpansionHandler;
-    @Inject
-    NotificationWakeUpCoordinator mWakeUpCoordinator;
-    @Inject
-    KeyguardBypassController mKeyguardBypassController;
-    @Inject
-    KeyguardStateController mKeyguardStateController;
-    @Inject
-    protected HeadsUpManagerPhone mHeadsUpManager;
-    @Inject
-    DynamicPrivacyController mDynamicPrivacyController;
-    @Inject
-    BypassHeadsUpNotifier mBypassHeadsUpNotifier;
-    @Nullable
-    @Inject
-    protected KeyguardLiftController mKeyguardLiftController;
-    @Inject
-    @Named(ALLOW_NOTIFICATION_LONG_PRESS_NAME)
-    boolean mAllowNotificationLongPress;
-    @Inject
-    protected NotifPipelineInitializer mNotifPipelineInitializer;
-    @Inject
-    protected FalsingManager mFalsingManager;
-
-    @VisibleForTesting
-    @Inject BroadcastDispatcher mBroadcastDispatcher;
+    private final StatusBarIconController mIconController;
+    private final DozeLog mDozeLog;
+    private final InjectionInflationController mInjectionInflater;
+    private final PulseExpansionHandler mPulseExpansionHandler;
+    private final NotificationWakeUpCoordinator mWakeUpCoordinator;
+    private final KeyguardBypassController mKeyguardBypassController;
+    private final KeyguardStateController mKeyguardStateController;
+    private final HeadsUpManagerPhone mHeadsUpManager;
+    private final DynamicPrivacyController mDynamicPrivacyController;
+    private final BypassHeadsUpNotifier mBypassHeadsUpNotifier;
+    private final boolean mAllowNotificationLongPress;
+    private final NotifPipelineInitializer mNotifPipelineInitializer;
+    private final FalsingManager mFalsingManager;
+    private final BroadcastDispatcher mBroadcastDispatcher;
+    private final ConfigurationController mConfigurationController;
+    private final StatusBarWindowViewController.Builder mStatusBarWindowViewControllerBuilder;
+    private final NotifLog mNotifLog;
 
     // expanded notifications
     protected NotificationPanelView mNotificationPanel; // the sliding/resizing panel within the notification window
@@ -413,7 +399,7 @@
     // RemoteInputView to be activated after unlock
     private View mPendingRemoteInputView;
 
-    @Inject RemoteInputQuickSettingsDisabler mRemoteInputQuickSettingsDisabler;
+    private final RemoteInputQuickSettingsDisabler mRemoteInputQuickSettingsDisabler;
 
     private View mReportRejectedTouch;
 
@@ -422,17 +408,17 @@
     private final int[] mAbsPos = new int[2];
     private final ArrayList<Runnable> mPostCollapseRunnables = new ArrayList<>();
 
-    @Inject NotificationGutsManager mGutsManager;
-    @Inject NotificationLogger mNotificationLogger;
-    @Inject NotificationEntryManager mEntryManager;
+    private final NotificationGutsManager mGutsManager;
+    private final NotificationLogger mNotificationLogger;
+    private final NotificationEntryManager mEntryManager;
     private NotificationListController mNotificationListController;
-    @Inject NotificationInterruptionStateProvider mNotificationInterruptionStateProvider;
-    @Inject NotificationViewHierarchyManager mViewHierarchyManager;
-    @Inject ForegroundServiceController mForegroundServiceController;
-    @Inject AppOpsController mAppOpsController;
-    @Inject KeyguardViewMediator mKeyguardViewMediator;
-    @Inject ZenModeController mZenController;
-    @Inject NotificationAlertingManager mNotificationAlertingManager;
+    private final NotificationInterruptionStateProvider mNotificationInterruptionStateProvider;
+    private final NotificationViewHierarchyManager mViewHierarchyManager;
+    private final ForegroundServiceController mForegroundServiceController;
+    private final AppOpsController mAppOpsController;
+    private final KeyguardViewMediator mKeyguardViewMediator;
+    private final ZenModeController mZenController;
+    private final NotificationAlertingManager mNotificationAlertingManager;
 
     // for disabling the status bar
     private int mDisabled1 = 0;
@@ -443,7 +429,7 @@
     private final Rect mLastFullscreenStackBounds = new Rect();
     private final Rect mLastDockedStackBounds = new Rect();
 
-    @Inject DisplayMetrics mDisplayMetrics;
+    private final DisplayMetrics mDisplayMetrics;
 
     // XXX: gesture research
     private final GestureRecorder mGestureRec = DEBUG_GESTURES
@@ -452,7 +438,7 @@
 
     private ScreenPinningRequest mScreenPinningRequest;
 
-    @Inject MetricsLogger mMetricsLogger;
+    private final MetricsLogger mMetricsLogger;
 
     // ensure quick settings is disabled until the current user makes it through the setup wizard
     @VisibleForTesting
@@ -489,14 +475,14 @@
     private ViewMediatorCallback mKeyguardViewMediatorCallback;
     protected ScrimController mScrimController;
     protected DozeScrimController mDozeScrimController;
-    @Inject UiOffloadThread mUiOffloadThread;
+    private final UiOffloadThread mUiOffloadThread;
 
     protected boolean mDozing;
     private boolean mDozingRequested;
 
-    @Inject NotificationMediaManager mMediaManager;
-    @Inject NotificationLockscreenUserManager mLockscreenUserManager;
-    @Inject NotificationRemoteInputManager mRemoteInputManager;
+    private final NotificationMediaManager mMediaManager;
+    private final NotificationLockscreenUserManager mLockscreenUserManager;
+    private final NotificationRemoteInputManager mRemoteInputManager;
     private boolean mWallpaperSupported;
 
     private final BroadcastReceiver mWallpaperChangedReceiver = new BroadcastReceiver() {
@@ -567,18 +553,18 @@
     };
 
     private KeyguardUserSwitcher mKeyguardUserSwitcher;
-    @Inject UserSwitcherController mUserSwitcherController;
-    @Inject NetworkController mNetworkController;
-    @Inject BatteryController mBatteryController;
+    private final UserSwitcherController mUserSwitcherController;
+    private final NetworkController mNetworkController;
+    private final BatteryController mBatteryController;
     protected boolean mPanelExpanded;
     private UiModeManager mUiModeManager;
     protected boolean mIsKeyguard;
     private LogMaker mStatusBarStateLog;
     protected NotificationIconAreaController mNotificationIconAreaController;
     @Nullable private View mAmbientIndicationContainer;
-    @Inject SysuiColorExtractor mColorExtractor;
-    @Inject ScreenLifecycle mScreenLifecycle;
-    @Inject @VisibleForTesting WakefulnessLifecycle mWakefulnessLifecycle;
+    private final SysuiColorExtractor mColorExtractor;
+    private final ScreenLifecycle mScreenLifecycle;
+    private final WakefulnessLifecycle mWakefulnessLifecycle;
 
     private final View.OnClickListener mGoToLockedShadeListener = v -> {
         if (mState == StatusBarState.KEYGUARD) {
@@ -587,7 +573,7 @@
         }
     };
     private boolean mNoAnimationOnNextBarModeChange;
-    @Inject SysuiStatusBarStateController mStatusBarStateController;
+    private final SysuiStatusBarStateController mStatusBarStateController;
 
     private final KeyguardUpdateMonitorCallback mUpdateCallback =
             new KeyguardUpdateMonitorCallback() {
@@ -601,24 +587,21 @@
                 @Override
                 public void onStrongAuthStateChanged(int userId) {
                     super.onStrongAuthStateChanged(userId);
-                    mEntryManager.updateNotifications();
+                    mEntryManager.updateNotifications("onStrongAuthStateChanged");
                 }
             };
     private final Handler mMainThreadHandler = new Handler(Looper.getMainLooper());
 
     private HeadsUpAppearanceController mHeadsUpAppearanceController;
     private boolean mVibrateOnOpening;
-    @Inject VibratorHelper mVibratorHelper;
+    private final VibratorHelper mVibratorHelper;
     private ActivityLaunchAnimator mActivityLaunchAnimator;
     protected StatusBarNotificationPresenter mPresenter;
     private NotificationActivityStarter mNotificationActivityStarter;
     private boolean mPulsing;
-    @Inject BubbleController mBubbleController;
-    private final BubbleController.BubbleExpandListener mBubbleExpandListener =
-            (isExpanding, key) -> {
-                mEntryManager.updateNotifications();
-                updateScrimController();
-            };
+    private final BubbleController mBubbleController;
+    private final BubbleController.BubbleExpandListener mBubbleExpandListener;
+
     private ActivityIntentHelper mActivityIntentHelper;
 
     @Override
@@ -635,6 +618,126 @@
             AppOpsManager.OP_COARSE_LOCATION,
             AppOpsManager.OP_FINE_LOCATION};
 
+    @Inject
+    public StatusBar(
+            Context context,
+            LightBarController lightBarController,
+            AutoHideController autoHideController,
+            KeyguardUpdateMonitor keyguardUpdateMonitor,
+            StatusBarIconController statusBarIconController,
+            DozeLog dozeLog,
+            InjectionInflationController injectionInflationController,
+            PulseExpansionHandler pulseExpansionHandler,
+            NotificationWakeUpCoordinator notificationWakeUpCoordinator,
+            KeyguardBypassController keyguardBypassController,
+            KeyguardStateController keyguardStateController,
+            HeadsUpManagerPhone headsUpManagerPhone,
+            DynamicPrivacyController dynamicPrivacyController,
+            BypassHeadsUpNotifier bypassHeadsUpNotifier,
+            @Named(ALLOW_NOTIFICATION_LONG_PRESS_NAME) boolean allowNotificationLongPress,
+            NotifPipelineInitializer notifPipelineInitializer,
+            FalsingManager falsingManager,
+            BroadcastDispatcher broadcastDispatcher,
+            RemoteInputQuickSettingsDisabler remoteInputQuickSettingsDisabler,
+            NotificationGutsManager notificationGutsManager,
+            NotificationLogger notificationLogger,
+            NotificationEntryManager notificationEntryManager,
+            NotificationInterruptionStateProvider notificationInterruptionStateProvider,
+            NotificationViewHierarchyManager notificationViewHierarchyManager,
+            ForegroundServiceController foregroundServiceController,
+            AppOpsController appOpsController,
+            KeyguardViewMediator keyguardViewMediator,
+            ZenModeController zenModeController,
+            NotificationAlertingManager notificationAlertingManager,
+            DisplayMetrics displayMetrics,
+            MetricsLogger metricsLogger,
+            UiOffloadThread uiOffloadThread,
+            NotificationMediaManager notificationMediaManager,
+            NotificationLockscreenUserManager lockScreenUserManager,
+            NotificationRemoteInputManager remoteInputManager,
+            UserSwitcherController userSwitcherController,
+            NetworkController networkController,
+            BatteryController batteryController,
+            SysuiColorExtractor colorExtractor,
+            ScreenLifecycle screenLifecycle,
+            WakefulnessLifecycle wakefulnessLifecycle,
+            SysuiStatusBarStateController statusBarStateController,
+            VibratorHelper vibratorHelper,
+            BubbleController bubbleController,
+            NotificationGroupManager groupManager,
+            NotificationGroupAlertTransferHelper groupAlertTransferHelper,
+            VisualStabilityManager visualStabilityManager,
+            DeviceProvisionedController deviceProvisionedController,
+            NavigationBarController navigationBarController,
+            AssistManager assistManager,
+            NotificationListener notificationListener,
+            ConfigurationController configurationController,
+            StatusBarWindowController statusBarWindowController,
+            StatusBarWindowViewController.Builder statusBarWindowViewControllerBuilder,
+            NotifLog notifLog) {
+        super(context);
+        mLightBarController = lightBarController;
+        mAutoHideController = autoHideController;
+        mKeyguardUpdateMonitor = keyguardUpdateMonitor;
+        mIconController = statusBarIconController;
+        mDozeLog = dozeLog;
+        mInjectionInflater = injectionInflationController;
+        mPulseExpansionHandler = pulseExpansionHandler;
+        mWakeUpCoordinator = notificationWakeUpCoordinator;
+        mKeyguardBypassController = keyguardBypassController;
+        mKeyguardStateController = keyguardStateController;
+        mHeadsUpManager = headsUpManagerPhone;
+        mDynamicPrivacyController = dynamicPrivacyController;
+        mBypassHeadsUpNotifier = bypassHeadsUpNotifier;
+        mAllowNotificationLongPress = allowNotificationLongPress;
+        mNotifPipelineInitializer = notifPipelineInitializer;
+        mFalsingManager = falsingManager;
+        mBroadcastDispatcher = broadcastDispatcher;
+        mRemoteInputQuickSettingsDisabler = remoteInputQuickSettingsDisabler;
+        mGutsManager = notificationGutsManager;
+        mNotificationLogger = notificationLogger;
+        mEntryManager = notificationEntryManager;
+        mNotificationInterruptionStateProvider = notificationInterruptionStateProvider;
+        mViewHierarchyManager = notificationViewHierarchyManager;
+        mForegroundServiceController = foregroundServiceController;
+        mAppOpsController = appOpsController;
+        mKeyguardViewMediator = keyguardViewMediator;
+        mZenController = zenModeController;
+        mNotificationAlertingManager = notificationAlertingManager;
+        mDisplayMetrics = displayMetrics;
+        mMetricsLogger = metricsLogger;
+        mUiOffloadThread = uiOffloadThread;
+        mMediaManager = notificationMediaManager;
+        mLockscreenUserManager = lockScreenUserManager;
+        mRemoteInputManager = remoteInputManager;
+        mUserSwitcherController = userSwitcherController;
+        mNetworkController = networkController;
+        mBatteryController = batteryController;
+        mColorExtractor = colorExtractor;
+        mScreenLifecycle = screenLifecycle;
+        mWakefulnessLifecycle = wakefulnessLifecycle;
+        mStatusBarStateController = statusBarStateController;
+        mVibratorHelper = vibratorHelper;
+        mBubbleController = bubbleController;
+        mGroupManager = groupManager;
+        mGroupAlertTransferHelper = groupAlertTransferHelper;
+        mVisualStabilityManager = visualStabilityManager;
+        mDeviceProvisionedController = deviceProvisionedController;
+        mNavigationBarController = navigationBarController;
+        mAssistManager = assistManager;
+        mNotificationListener = notificationListener;
+        mConfigurationController = configurationController;
+        mStatusBarWindowController = statusBarWindowController;
+        mStatusBarWindowViewControllerBuilder = statusBarWindowViewControllerBuilder;
+        mNotifLog = notifLog;
+
+        mBubbleExpandListener =
+                (isExpanding, key) -> {
+                    mEntryManager.updateNotifications("onBubbleExpandChanged");
+                    updateScrimController();
+                };
+    }
+
     @Override
     public void start() {
         mNotificationListener.registerAsSystemService();
@@ -772,7 +875,7 @@
 
         Dependency.get(ActivityStarterDelegate.class).setActivityStarterImpl(this);
 
-        Dependency.get(ConfigurationController.class).addCallback(this);
+        mConfigurationController.addCallback(this);
 
         // set the initial view visibility
         Dependency.get(InitController.class).addPostInitTask(this::updateAreThereNotifications);
@@ -792,8 +895,7 @@
         updateTheme();
 
         inflateStatusBarWindow(context);
-        mStatusBarWindow.setService(this);
-        mStatusBarWindow.setBypassController(mKeyguardBypassController);
+        mStatusBarWindowViewController.setService(this);
         mStatusBarWindow.setOnTouchListener(getStatusBarWindowTouchListener());
 
         // TODO: Deal with the ugliness that comes from having some of the statusbar broken out
@@ -805,6 +907,8 @@
         NotificationListContainer notifListContainer = (NotificationListContainer) mStackScroller;
         mNotificationLogger.setUpWithContainer(notifListContainer);
 
+        // TODO: make this injectable. Currently that would create a circular dependency between
+        // NotificationIconAreaController and StatusBar.
         mNotificationIconAreaController = SystemUIFactory.getInstance()
                 .createNotificationIconAreaController(context, this,
                         mWakeUpCoordinator, mKeyguardBypassController,
@@ -857,9 +961,9 @@
                     mHeadsUpAppearanceController = new HeadsUpAppearanceController(
                             mNotificationIconAreaController, mHeadsUpManager, mStatusBarWindow,
                             mStatusBarStateController, mKeyguardBypassController,
-                            mWakeUpCoordinator);
+                            mKeyguardStateController, mWakeUpCoordinator);
                     mHeadsUpAppearanceController.readFrom(oldController);
-                    mStatusBarWindow.setStatusBarView(mStatusBarView);
+                    mStatusBarWindowViewController.setStatusBarView(mStatusBarView);
                     updateAreThereNotifications();
                     checkBarModes();
                 }).getFragmentManager()
@@ -869,7 +973,7 @@
                 .commit();
 
         mHeadsUpManager.setUp(mStatusBarWindow, mGroupManager, this, mVisualStabilityManager);
-        Dependency.get(ConfigurationController.class).addCallback(mHeadsUpManager);
+        mConfigurationController.addCallback(mHeadsUpManager);
         mHeadsUpManager.addListener(this);
         mHeadsUpManager.addListener(mNotificationPanel);
         mHeadsUpManager.addListener(mGroupManager);
@@ -926,7 +1030,7 @@
                         mStatusBarWindowController.setScrimsVisibility(scrimsVisible);
                     }
                     if (mStatusBarWindow != null) {
-                        mStatusBarWindow.onScrimVisibilityChanged(scrimsVisible);
+                        mStatusBarWindowViewController.onScrimVisibilityChanged(scrimsVisible);
                     }
                 }, DozeParameters.getInstance(mContext),
                 mContext.getSystemService(AlarmManager.class),
@@ -949,7 +1053,7 @@
         }
 
         mNotificationPanel.setLaunchAffordanceListener(
-                mStatusBarWindow::onShowingLaunchAffordanceChanged);
+                mStatusBarWindowViewController::onShowingLaunchAffordanceChanged);
 
         // Set up the quick settings tile panel
         View container = mStatusBarWindow.findViewById(R.id.qs_frame);
@@ -1004,11 +1108,10 @@
             });
         }
 
-        PowerManager pm = (PowerManager) mContext.getSystemService(Context.POWER_SERVICE);
-        if (!pm.isScreenOn()) {
+        if (!mPowerManager.isScreenOn()) {
             mBroadcastReceiver.onReceive(mContext, new Intent(Intent.ACTION_SCREEN_OFF));
         }
-        mGestureWakeLock = pm.newWakeLock(PowerManager.SCREEN_BRIGHT_WAKE_LOCK,
+        mGestureWakeLock = mPowerManager.newWakeLock(PowerManager.SCREEN_BRIGHT_WAKE_LOCK,
                 "GestureWakeLock");
         mVibrator = mContext.getSystemService(Vibrator.class);
         int[] pattern = mContext.getResources().getIntArray(
@@ -1056,7 +1159,7 @@
     private void setUpPresenter() {
         // Set up the initial notification state.
         mActivityLaunchAnimator = new ActivityLaunchAnimator(
-                mStatusBarWindow, this, mNotificationPanel,
+                mStatusBarWindowViewController, this, mNotificationPanel,
                 (NotificationListContainer) mStackScroller);
 
         final NotificationRowBinderImpl rowBinder =
@@ -1064,12 +1167,13 @@
                         mContext,
                         mAllowNotificationLongPress,
                         mKeyguardBypassController,
-                        mStatusBarStateController);
+                        mStatusBarStateController,
+                        mNotifLog);
 
         mPresenter = new StatusBarNotificationPresenter(mContext, mNotificationPanel,
                 mHeadsUpManager, mStatusBarWindow, mStackScroller, mDozeScrimController,
                 mScrimController, mActivityLaunchAnimator, mDynamicPrivacyController,
-                mNotificationAlertingManager, rowBinder);
+                mNotificationAlertingManager, rowBinder, mKeyguardStateController);
 
         mNotificationListController =
                 new NotificationListController(
@@ -1131,8 +1235,8 @@
     @Override
     public void wakeUpIfDozing(long time, View where, String why) {
         if (mDozing) {
-            PowerManager pm = mContext.getSystemService(PowerManager.class);
-            pm.wakeUp(time, PowerManager.WAKE_REASON_GESTURE, "com.android.systemui:" + why);
+            mPowerManager.wakeUp(
+                    time, PowerManager.WAKE_REASON_GESTURE, "com.android.systemui:" + why);
             mWakeUpComingFromTouch = true;
             where.getLocationInWindow(mTmpInt2);
             mWakeUpTouchLocation = new PointF(mTmpInt2[0] + where.getWidth() / 2,
@@ -1228,17 +1332,20 @@
     protected void inflateStatusBarWindow(Context context) {
         mStatusBarWindow = (StatusBarWindowView) mInjectionInflater.injectable(
                 LayoutInflater.from(context)).inflate(R.layout.super_status_bar, null);
+        mStatusBarWindowViewController = mStatusBarWindowViewControllerBuilder
+                .setStatusBarWindowView(mStatusBarWindow)
+                .setShadeController(this)
+                .build();
     }
 
     protected void startKeyguard() {
         Trace.beginSection("StatusBar#startKeyguard");
-        KeyguardViewMediator keyguardViewMediator = getComponent(KeyguardViewMediator.class);
         mBiometricUnlockController = new BiometricUnlockController(mContext,
-                mDozeScrimController, keyguardViewMediator,
+                mDozeScrimController, mKeyguardViewMediator,
                 mScrimController, this, mKeyguardStateController, new Handler(),
                 mKeyguardUpdateMonitor, mKeyguardBypassController);
         putComponent(BiometricUnlockController.class, mBiometricUnlockController);
-        mStatusBarKeyguardViewManager = keyguardViewMediator.registerStatusBar(this,
+        mStatusBarKeyguardViewManager = mKeyguardViewMediator.registerStatusBar(this,
                 getBouncerContainer(), mNotificationPanel, mBiometricUnlockController,
                 mStatusBarWindow.findViewById(R.id.lock_icon_container), mStackScroller,
                 mKeyguardBypassController);
@@ -1248,7 +1355,7 @@
         mRemoteInputManager.getController().addCallback(mStatusBarKeyguardViewManager);
         mDynamicPrivacyController.setStatusBarKeyguardViewManager(mStatusBarKeyguardViewManager);
 
-        mKeyguardViewMediatorCallback = keyguardViewMediator.getViewMediatorCallback();
+        mKeyguardViewMediatorCallback = mKeyguardViewMediator.getViewMediatorCallback();
         mLightBarController.setBiometricUnlockController(mBiometricUnlockController);
         mMediaManager.setBiometricUnlockController(mBiometricUnlockController);
         Dependency.get(KeyguardDismissUtil.class).setDismissHandler(this::executeWhenUnlocked);
@@ -1344,8 +1451,12 @@
         return mZenController.areNotificationsHiddenInShade();
     }
 
-    public void requestNotificationUpdate() {
-        mEntryManager.updateNotifications();
+    /**
+     * Request a notification update
+     * @param reason why we're requesting a notification update
+     */
+    public void requestNotificationUpdate(String reason) {
+        mEntryManager.updateNotifications(reason);
     }
 
     /**
@@ -1586,7 +1697,7 @@
 
     @Override
     public void onHeadsUpStateChanged(NotificationEntry entry, boolean isHeadsUp) {
-        mEntryManager.updateNotifications();
+        mEntryManager.updateNotifications("onHeadsUpStateChanged");
         if (isDozing() && isHeadsUp) {
             entry.setPulseSuppressed(false);
             mDozeServiceHost.fireNotificationPulse(entry);
@@ -1734,6 +1845,16 @@
         return mPresenter;
     }
 
+    @VisibleForTesting
+    void setBarStateForTest(int state) {
+        mState = state;
+    }
+
+    @VisibleForTesting
+    void setUserSetupForTest(boolean userSetup) {
+        mUserSetup = userSetup;
+    }
+
     /**
      * All changes to the status bar and notifications funnel through here and are batched.
      */
@@ -1921,7 +2042,7 @@
             // release focus immediately to kick off focus change transition
             mStatusBarWindowController.setStatusBarFocusable(false);
 
-            mStatusBarWindow.cancelExpandHelper();
+            mStatusBarWindowViewController.cancelExpandHelper();
             mStatusBarView.collapsePanel(true /* animate */, delayed, speedUpFactor);
         } else {
             mBubbleController.collapseStack();
@@ -2312,8 +2433,8 @@
             dumpBarTransitions(pw, "mStatusBarView", mStatusBarView.getBarTransitions());
         }
         pw.println("  StatusBarWindowView: ");
-        if (mStatusBarWindow != null) {
-            mStatusBarWindow.dump(fd, pw, args);
+        if (mStatusBarWindowViewController != null) {
+            mStatusBarWindowViewController.dump(fd, pw, args);
         }
 
         pw.println("  mMediaManager: ");
@@ -2425,7 +2546,6 @@
 
     public void createAndAddWindows(@Nullable RegisterStatusBarResult result) {
         makeStatusBarView(result);
-        mStatusBarWindowController = Dependency.get(StatusBarWindowController.class);
         mStatusBarWindowController.add(mStatusBarWindow, getStatusBarHeight());
     }
 
@@ -2669,7 +2789,6 @@
         }
     }
 
-    // SystemUIService notifies SystemBars of configuration changes, which then calls down here
     @Override
     public void onConfigChanged(Configuration newConfig) {
         updateResources();
@@ -3251,7 +3370,7 @@
         final int themeResId = lockDarkText ? R.style.Theme_SystemUI_Light : R.style.Theme_SystemUI;
         if (mContext.getThemeResId() != themeResId) {
             mContext.setTheme(themeResId);
-            Dependency.get(ConfigurationController.class).notifyThemeChanged();
+            mConfigurationController.notifyThemeChanged();
         }
     }
 
@@ -3459,7 +3578,7 @@
         updateQsExpansionEnabled();
         mKeyguardViewMediator.setDozing(mDozing);
 
-        mEntryManager.updateNotifications();
+        mEntryManager.updateNotifications("onDozingChanged");
         updateDozingState();
         updateScrimController();
         updateReportRejectedTouchVisibility();
@@ -3483,7 +3602,6 @@
 
     private void updateKeyguardState() {
         mKeyguardStateController.notifyKeyguardState(mStatusBarKeyguardViewManager.isShowing(),
-                mKeyguardStateController.isMethodSecure(),
                 mStatusBarKeyguardViewManager.isOccluded());
     }
 
@@ -3609,7 +3727,7 @@
         mBouncerShowing = bouncerShowing;
         mKeyguardBypassController.setBouncerShowing(bouncerShowing);
         mPulseExpansionHandler.setBouncerShowing(bouncerShowing);
-        mStatusBarWindow.setBouncerShowingScrimmed(isBouncerShowingScrimmed());
+        mStatusBarWindowViewController.setBouncerShowingScrimmed(isBouncerShowingScrimmed());
         if (mStatusBarView != null) mStatusBarView.setBouncerShowing(bouncerShowing);
         updateHideIconsForBouncer(true /* animate */);
         mCommandQueue.recomputeDisableFlags(mDisplayId, true /* animate */);
@@ -3624,7 +3742,7 @@
      */
     public void collapseShade() {
         if (mNotificationPanel.isTracking()) {
-            mStatusBarWindow.cancelCurrentTouch();
+            mStatusBarWindowViewController.cancelCurrentTouch();
         }
         if (mPanelExpanded && mState == StatusBarState.SHADE) {
             animateCollapsePanels();
@@ -3645,7 +3763,7 @@
             updateVisibleToUser();
 
             updateNotificationPanelTouchState();
-            mStatusBarWindow.cancelCurrentTouch();
+            mStatusBarWindowViewController.cancelCurrentTouch();
             if (mLaunchCameraOnFinishedGoingToSleep) {
                 mLaunchCameraOnFinishedGoingToSleep = false;
 
@@ -3798,8 +3916,7 @@
             return;
         }
         if (!mDeviceInteractive) {
-            PowerManager pm = mContext.getSystemService(PowerManager.class);
-            pm.wakeUp(SystemClock.uptimeMillis(), PowerManager.WAKE_REASON_CAMERA_LAUNCH,
+            mPowerManager.wakeUp(SystemClock.uptimeMillis(), PowerManager.WAKE_REASON_CAMERA_LAUNCH,
                     "com.android.systemui:CAMERA_GESTURE");
         }
         vibrateForCameraGesture();
@@ -3838,20 +3955,17 @@
     }
 
     boolean isCameraAllowedByAdmin() {
-        // TODO(b/140060745)
-        return whitelistIpcs(() -> {
-            if (mDevicePolicyManager.getCameraDisabled(null,
-                    mLockscreenUserManager.getCurrentUserId())) {
-                return false;
-            } else if (mStatusBarKeyguardViewManager == null
-                    || (isKeyguardShowing() && isKeyguardSecure())) {
-                // Check if the admin has disabled the camera specifically for the keyguard
-                return (mDevicePolicyManager.getKeyguardDisabledFeatures(null,
-                        mLockscreenUserManager.getCurrentUserId())
-                        & DevicePolicyManager.KEYGUARD_DISABLE_SECURE_CAMERA) == 0;
-            }
-            return true;
-        });
+        if (mDevicePolicyManager.getCameraDisabled(null,
+                mLockscreenUserManager.getCurrentUserId())) {
+            return false;
+        } else if (mStatusBarKeyguardViewManager == null
+                || (isKeyguardShowing() && isKeyguardSecure())) {
+            // Check if the admin has disabled the camera specifically for the keyguard
+            return (mDevicePolicyManager.getKeyguardDisabledFeatures(null,
+                    mLockscreenUserManager.getCurrentUserId())
+                    & DevicePolicyManager.KEYGUARD_DISABLE_SECURE_CAMERA) == 0;
+        }
+        return true;
     }
 
     private boolean isGoingToSleep() {
@@ -3867,7 +3981,8 @@
     public void notifyBiometricAuthModeChanged() {
         updateDozing();
         updateScrimController();
-        mStatusBarWindow.onBiometricAuthModeChanged(mBiometricUnlockController.isWakeAndUnlock(),
+        mStatusBarWindowViewController.onBiometricAuthModeChanged(
+                mBiometricUnlockController.isWakeAndUnlock(),
                 mBiometricUnlockController.isBiometricUnlock());
     }
 
@@ -3988,7 +4103,7 @@
             }
 
             if (reason == DozeEvent.PULSE_REASON_DOCKING && mStatusBarWindow != null) {
-                mStatusBarWindow.suppressWakeUpGesture(true);
+                mStatusBarWindowViewController.suppressWakeUpGesture(true);
             }
 
             boolean passiveAuthInterrupt = reason == DozeEvent.PULSE_REASON_SENSOR_WAKE_LOCK_SCREEN
@@ -4012,7 +4127,7 @@
                     updateNotificationPanelTouchState();
                     mScrimController.setWakeLockScreenSensorActive(false);
                     if (mStatusBarWindow != null) {
-                        mStatusBarWindow.suppressWakeUpGesture(false);
+                        mStatusBarWindowViewController.suppressWakeUpGesture(false);
                     }
                     setPulsing(false);
                 }
@@ -4023,7 +4138,7 @@
                     mKeyguardViewMediator.setPulsing(pulsing);
                     mNotificationPanel.setPulsing(pulsing);
                     mVisualStabilityManager.setPulsing(pulsing);
-                    mStatusBarWindow.setPulsing(pulsing);
+                    mStatusBarWindowViewController.setPulsing(pulsing);
                     mIgnoreTouchWhilePulsing = false;
                     if (mKeyguardUpdateMonitor != null && passiveAuthInterrupt) {
                         mKeyguardUpdateMonitor.onAuthInterruptDetected(pulsing /* active */);
@@ -4054,7 +4169,7 @@
             }
             mIgnoreTouchWhilePulsing = ignore;
             if (isDozing() && ignore) {
-                mStatusBarWindow.cancelCurrentTouch();
+                mStatusBarWindowViewController.cancelCurrentTouch();
             }
         }
 
@@ -4188,11 +4303,11 @@
     // all notifications
     protected ViewGroup mStackScroller;
 
-    @Inject NotificationGroupManager mGroupManager;
-    @Inject NotificationGroupAlertTransferHelper mGroupAlertTransferHelper;
+    private final NotificationGroupManager mGroupManager;
+    private final NotificationGroupAlertTransferHelper mGroupAlertTransferHelper;
 
     // handling reordering
-    @Inject VisualStabilityManager mVisualStabilityManager;
+    private final VisualStabilityManager mVisualStabilityManager;
 
     protected AccessibilityManager mAccessibilityManager;
 
@@ -4208,9 +4323,9 @@
     protected StatusBarKeyguardViewManager mStatusBarKeyguardViewManager;
 
     protected KeyguardManager mKeyguardManager;
-    @Inject DeviceProvisionedController mDeviceProvisionedController;
+    private final DeviceProvisionedController mDeviceProvisionedController;
 
-    @Inject protected NavigationBarController mNavigationBarController;
+    private final NavigationBarController mNavigationBarController;
 
     // UI-specific methods
 
@@ -4226,7 +4341,7 @@
     protected NotificationShelf mNotificationShelf;
     protected EmptyShadeView mEmptyShadeView;
 
-    @Inject AssistManager mAssistManager;
+    private final AssistManager mAssistManager;
 
     public boolean isDeviceInteractive() {
         return mDeviceInteractive;
@@ -4285,7 +4400,7 @@
         }
     }
 
-    @Inject NotificationListener mNotificationListener;
+    private final NotificationListener mNotificationListener;
 
     public void setNotificationSnoozed(StatusBarNotification sbn, SnoozeOption snoozeOption) {
         if (snoozeOption.getSnoozeCriterion() != null) {
@@ -4509,7 +4624,7 @@
      */
     public void onBouncerPreHideAnimation() {
         mNotificationPanel.onBouncerPreHideAnimation();
-        mStatusBarWindow.onBouncerPreHideAnimation();
+        mStatusBarWindowViewController.onBouncerPreHideAnimation();
     }
 
     /**
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java
index df23f8ca..8683586 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java
@@ -33,6 +33,8 @@
 import android.view.ViewRootImpl;
 import android.view.WindowManagerGlobal;
 
+import androidx.annotation.VisibleForTesting;
+
 import com.android.internal.util.LatencyTracker;
 import com.android.internal.widget.LockPatternUtils;
 import com.android.keyguard.KeyguardUpdateMonitor;
@@ -160,6 +162,7 @@
     private boolean mLastLockVisible;
 
     private OnDismissAction mAfterKeyguardGoneAction;
+    private Runnable mKeyguardGoneCancelAction;
     private final ArrayList<Runnable> mAfterKeyguardGoneRunnables = new ArrayList<>();
 
     // Dismiss action to be launched when we stop dozing or the keyguard is gone.
@@ -298,8 +301,7 @@
     public void show(Bundle options) {
         mShowing = true;
         mStatusBarWindowController.setKeyguardShowing(true);
-        mKeyguardStateController.notifyKeyguardState(
-                mShowing, mKeyguardStateController.isMethodSecure(),
+        mKeyguardStateController.notifyKeyguardState(mShowing,
                 mKeyguardStateController.isOccluded());
         reset(true /* hideBouncerWhenShowing */);
         StatsLog.write(StatsLog.KEYGUARD_STATE_CHANGED,
@@ -329,10 +331,20 @@
         return false;
     }
 
-    private void hideBouncer(boolean destroyView) {
+    @VisibleForTesting
+    void hideBouncer(boolean destroyView) {
         if (mBouncer == null) {
             return;
         }
+        if (mShowing) {
+            // If we were showing the bouncer and then aborting, we need to also clear out any
+            // potential actions unless we actually unlocked.
+            mAfterKeyguardGoneAction = null;
+            if (mKeyguardGoneCancelAction != null) {
+                mKeyguardGoneCancelAction.run();
+                mKeyguardGoneCancelAction = null;
+            }
+        }
         mBouncer.hide(destroyView);
         cancelPendingWakeupAction();
     }
@@ -365,6 +377,7 @@
                 mBouncer.showWithDismissAction(r, cancelAction);
             } else {
                 mAfterKeyguardGoneAction = r;
+                mKeyguardGoneCancelAction = cancelAction;
                 mBouncer.show(false /* resetSecuritySelection */);
             }
         }
@@ -531,7 +544,7 @@
     public void hide(long startTime, long fadeoutDuration) {
         mShowing = false;
         mKeyguardStateController.notifyKeyguardState(mShowing,
-                mKeyguardStateController.isMethodSecure(), mKeyguardStateController.isOccluded());
+                mKeyguardStateController.isOccluded());
         launchPendingWakeupAction();
 
         if (Dependency.get(KeyguardUpdateMonitor.class).needsSlowUnlockTransition()) {
@@ -672,6 +685,7 @@
             mAfterKeyguardGoneAction.onDismiss();
             mAfterKeyguardGoneAction = null;
         }
+        mKeyguardGoneCancelAction = null;
         for (int i = 0; i < mAfterKeyguardGoneRunnables.size(); i++) {
             mAfterKeyguardGoneRunnables.get(i).run();
         }
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 3e0c268..f4a26ba 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarNotificationPresenter.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarNotificationPresenter.java
@@ -89,8 +89,7 @@
 
     private final ShadeController mShadeController = Dependency.get(ShadeController.class);
     private final ActivityStarter mActivityStarter = Dependency.get(ActivityStarter.class);
-    private final KeyguardStateController mKeyguardStateController = Dependency.get(
-            KeyguardStateController.class);
+    private final KeyguardStateController mKeyguardStateController;
     private final NotificationViewHierarchyManager mViewHierarchyManager =
             Dependency.get(NotificationViewHierarchyManager.class);
     private final NotificationLockscreenUserManager mLockscreenUserManager =
@@ -139,8 +138,10 @@
             ActivityLaunchAnimator activityLaunchAnimator,
             DynamicPrivacyController dynamicPrivacyController,
             NotificationAlertingManager notificationAlertingManager,
-            NotificationRowBinderImpl notificationRowBinder) {
+            NotificationRowBinderImpl notificationRowBinder,
+            KeyguardStateController keyguardStateController) {
         mContext = context;
+        mKeyguardStateController = keyguardStateController;
         mNotificationPanel = panel;
         mHeadsUpManager = headsUp;
         mDynamicPrivacyController = dynamicPrivacyController;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarRemoteInputCallback.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarRemoteInputCallback.java
index 9a281ce..1def89b 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarRemoteInputCallback.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarRemoteInputCallback.java
@@ -35,7 +35,6 @@
 import android.view.ViewParent;
 
 import com.android.systemui.ActivityIntentHelper;
-import com.android.systemui.Dependency;
 import com.android.systemui.plugins.ActivityStarter;
 import com.android.systemui.plugins.statusbar.StatusBarStateController;
 import com.android.systemui.statusbar.CommandQueue;
@@ -58,19 +57,16 @@
 public class StatusBarRemoteInputCallback implements Callback, Callbacks,
         StatusBarStateController.StateListener {
 
-    private final KeyguardStateController mKeyguardStateController = Dependency.get(
-            KeyguardStateController.class);
-    private final SysuiStatusBarStateController mStatusBarStateController =
-            (SysuiStatusBarStateController) Dependency.get(StatusBarStateController.class);
-    private final NotificationLockscreenUserManager mLockscreenUserManager =
-            Dependency.get(NotificationLockscreenUserManager.class);
-    private final ActivityStarter mActivityStarter = Dependency.get(ActivityStarter.class);
+    private final KeyguardStateController mKeyguardStateController;
+    private final SysuiStatusBarStateController mStatusBarStateController;
+    private final NotificationLockscreenUserManager mLockscreenUserManager;
+    private final ActivityStarter mActivityStarter;
+    private final ShadeController mShadeController;
     private final Context mContext;
     private final ActivityIntentHelper mActivityIntentHelper;
     private final NotificationGroupManager mGroupManager;
     private View mPendingWorkRemoteInputView;
     private View mPendingRemoteInputView;
-    private final ShadeController mShadeController = Dependency.get(ShadeController.class);
     private KeyguardManager mKeyguardManager;
     private final CommandQueue mCommandQueue;
     private int mDisabled2;
@@ -80,10 +76,19 @@
     /**
      */
     @Inject
-    public StatusBarRemoteInputCallback(Context context, NotificationGroupManager groupManager) {
+    public StatusBarRemoteInputCallback(Context context, NotificationGroupManager groupManager,
+            NotificationLockscreenUserManager notificationLockscreenUserManager,
+            KeyguardStateController keyguardStateController,
+            StatusBarStateController statusBarStateController,
+            ActivityStarter activityStarter, ShadeController shadeController) {
         mContext = context;
         mContext.registerReceiverAsUser(mChallengeReceiver, UserHandle.ALL,
                 new IntentFilter(ACTION_DEVICE_LOCKED_CHANGED), null, null);
+        mLockscreenUserManager = notificationLockscreenUserManager;
+        mKeyguardStateController = keyguardStateController;
+        mStatusBarStateController = (SysuiStatusBarStateController) statusBarStateController;
+        mShadeController = shadeController;
+        mActivityStarter = activityStarter;
         mStatusBarStateController.addCallback(this);
         mKeyguardManager = context.getSystemService(KeyguardManager.class);
         mCommandQueue = getComponent(context, CommandQueue.class);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowView.java
index a9e818d..d04c7bd 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowView.java
@@ -19,29 +19,18 @@
 import android.annotation.ColorInt;
 import android.annotation.DrawableRes;
 import android.annotation.LayoutRes;
-import android.app.StatusBarManager;
 import android.content.Context;
 import android.content.res.Configuration;
 import android.content.res.TypedArray;
 import android.graphics.Canvas;
 import android.graphics.Paint;
-import android.graphics.PorterDuff;
-import android.graphics.PorterDuffXfermode;
 import android.graphics.Rect;
 import android.graphics.drawable.Drawable;
-import android.hardware.display.AmbientDisplayConfiguration;
-import android.media.AudioManager;
-import android.media.session.MediaSessionLegacyHelper;
 import android.net.Uri;
 import android.os.Bundle;
-import android.os.SystemClock;
-import android.os.UserHandle;
-import android.provider.Settings;
 import android.util.AttributeSet;
 import android.view.ActionMode;
 import android.view.DisplayCutout;
-import android.view.GestureDetector;
-import android.view.InputDevice;
 import android.view.InputQueue;
 import android.view.KeyEvent;
 import android.view.LayoutInflater;
@@ -56,21 +45,9 @@
 import android.view.WindowInsetsController;
 import android.widget.FrameLayout;
 
-import com.android.internal.annotations.VisibleForTesting;
 import com.android.internal.view.FloatingActionMode;
 import com.android.internal.widget.FloatingToolbar;
-import com.android.systemui.Dependency;
-import com.android.systemui.ExpandHelper;
 import com.android.systemui.R;
-import com.android.systemui.plugins.FalsingManager;
-import com.android.systemui.plugins.statusbar.StatusBarStateController;
-import com.android.systemui.statusbar.DragDownHelper;
-import com.android.systemui.statusbar.notification.stack.NotificationStackScrollLayout;
-import com.android.systemui.statusbar.phone.ScrimController.ScrimVisibility;
-import com.android.systemui.tuner.TunerService;
-
-import java.io.FileDescriptor;
-import java.io.PrintWriter;
 
 /**
  * Combined status bar and notification panel view. Also holding backdrop and scrims.
@@ -79,87 +56,21 @@
     public static final String TAG = "StatusBarWindowView";
     public static final boolean DEBUG = StatusBar.DEBUG;
 
-    private final GestureDetector mGestureDetector;
-    private final StatusBarStateController mStatusBarStateController;
-    private boolean mDoubleTapEnabled;
-    private boolean mSingleTapEnabled;
-    private DragDownHelper mDragDownHelper;
-    private NotificationStackScrollLayout mStackScrollLayout;
-    private NotificationPanelView mNotificationPanel;
-    private View mBrightnessMirror;
-    private LockIcon mLockIcon;
-    private PhoneStatusBarView mStatusBarView;
-
     private int mRightInset = 0;
     private int mLeftInset = 0;
 
-    private StatusBar mService;
-    private final Paint mTransparentSrcPaint = new Paint();
-    private FalsingManager mFalsingManager;
-
     // Implements the floating action mode for TextView's Cut/Copy/Past menu. Normally provided by
     // DecorView, but since this is a special window we have to roll our own.
     private View mFloatingActionModeOriginatingView;
     private ActionMode mFloatingActionMode;
     private FloatingToolbar mFloatingToolbar;
     private ViewTreeObserver.OnPreDrawListener mFloatingToolbarPreDrawListener;
-    private boolean mTouchCancelled;
-    private boolean mTouchActive;
-    private boolean mExpandAnimationRunning;
-    private boolean mExpandAnimationPending;
-    private boolean mSuppressingWakeUpGesture;
 
-    private final GestureDetector.SimpleOnGestureListener mGestureListener =
-            new GestureDetector.SimpleOnGestureListener() {
-        @Override
-        public boolean onSingleTapConfirmed(MotionEvent e) {
-            if (mSingleTapEnabled && !mSuppressingWakeUpGesture) {
-                mService.wakeUpIfDozing(SystemClock.uptimeMillis(), StatusBarWindowView.this,
-                        "SINGLE_TAP");
-                return true;
-            }
-            return false;
-        }
-
-        @Override
-        public boolean onDoubleTap(MotionEvent e) {
-            if (mDoubleTapEnabled || mSingleTapEnabled) {
-                mService.wakeUpIfDozing(SystemClock.uptimeMillis(), StatusBarWindowView.this,
-                        "DOUBLE_TAP");
-                return true;
-            }
-            return false;
-        }
-    };
-    private final TunerService.Tunable mTunable = (key, newValue) -> {
-        AmbientDisplayConfiguration configuration = new AmbientDisplayConfiguration(mContext);
-        switch (key) {
-            case Settings.Secure.DOZE_DOUBLE_TAP_GESTURE:
-                mDoubleTapEnabled = configuration.doubleTapGestureEnabled(UserHandle.USER_CURRENT);
-                break;
-            case Settings.Secure.DOZE_TAP_SCREEN_GESTURE:
-                mSingleTapEnabled = configuration.tapGestureEnabled(UserHandle.USER_CURRENT);
-        }
-    };
-
-    /**
-     * If set to true, the current gesture started below the notch and we need to dispatch touch
-     * events manually as it's outside of the regular view bounds.
-     */
-    private boolean mExpandingBelowNotch;
-    private KeyguardBypassController mBypassController;
+    private InteractionEventHandler mInteractionEventHandler;
 
     public StatusBarWindowView(Context context, AttributeSet attrs) {
         super(context, attrs);
         setMotionEventSplittingEnabled(false);
-        mTransparentSrcPaint.setColor(0);
-        mTransparentSrcPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC));
-        mFalsingManager = Dependency.get(FalsingManager.class);  // TODO: inject into a controller.
-        mGestureDetector = new GestureDetector(context, mGestureListener);
-        mStatusBarStateController = Dependency.get(StatusBarStateController.class);
-        Dependency.get(TunerService.class).addTunable(mTunable,
-                Settings.Secure.DOZE_DOUBLE_TAP_GESTURE,
-                Settings.Secure.DOZE_TAP_SCREEN_GESTURE);
     }
 
     @Override
@@ -226,11 +137,6 @@
         }
     }
 
-    @VisibleForTesting
-    protected NotificationStackScrollLayout getStackScrollLayout() {
-        return mStackScrollLayout;
-    }
-
     @Override
     public FrameLayout.LayoutParams generateLayoutParams(AttributeSet attrs) {
         return new LayoutParams(getContext(), attrs);
@@ -242,61 +148,6 @@
     }
 
     @Override
-    protected void onFinishInflate() {
-        super.onFinishInflate();
-        mStackScrollLayout = findViewById(R.id.notification_stack_scroller);
-        mNotificationPanel = findViewById(R.id.notification_panel);
-        mBrightnessMirror = findViewById(R.id.brightness_mirror);
-        mLockIcon = findViewById(R.id.lock_icon);
-    }
-
-    @Override
-    public void onViewAdded(View child) {
-        super.onViewAdded(child);
-        if (child.getId() == R.id.brightness_mirror) {
-            mBrightnessMirror = child;
-        }
-    }
-
-    /**
-     * Propagate {@link StatusBar} pulsing state.
-     */
-    public void setPulsing(boolean pulsing) {
-        if (mLockIcon != null) {
-            mLockIcon.setPulsing(pulsing);
-        }
-    }
-
-    /**
-     * Called when the biometric authentication mode changes.
-     * @param wakeAndUnlock If the type is {@link BiometricUnlockController#isWakeAndUnlock()}
-     * @param isUnlock If the type is {@link BiometricUnlockController#isBiometricUnlock()} ()
-     */
-    public void onBiometricAuthModeChanged(boolean wakeAndUnlock, boolean isUnlock) {
-        if (mLockIcon != null) {
-            mLockIcon.onBiometricAuthModeChanged(wakeAndUnlock, isUnlock);
-        }
-    }
-
-    public void setStatusBarView(PhoneStatusBarView statusBarView) {
-        mStatusBarView = statusBarView;
-    }
-
-    public void setService(StatusBar service) {
-        mService = service;
-        NotificationStackScrollLayout stackScrollLayout = getStackScrollLayout();
-        ExpandHelper.Callback expandHelperCallback = stackScrollLayout.getExpandHelperCallback();
-        DragDownHelper.DragDownCallback dragDownCallback = stackScrollLayout.getDragDownCallback();
-        setDragDownHelper(new DragDownHelper(getContext(), this, expandHelperCallback,
-                dragDownCallback, mFalsingManager));
-    }
-
-    @VisibleForTesting
-    void setDragDownHelper(DragDownHelper dragDownHelper) {
-        mDragDownHelper = dragDownHelper;
-    }
-
-    @Override
     protected void onAttachedToWindow () {
         super.onAttachedToWindow();
         setWillNotDraw(!DEBUG);
@@ -304,152 +155,53 @@
 
     @Override
     public boolean dispatchKeyEvent(KeyEvent event) {
-        if (mService.interceptMediaKey(event)) {
+        if (mInteractionEventHandler.interceptMediaKey(event)) {
             return true;
         }
+
         if (super.dispatchKeyEvent(event)) {
             return true;
         }
-        boolean down = event.getAction() == KeyEvent.ACTION_DOWN;
-        switch (event.getKeyCode()) {
-            case KeyEvent.KEYCODE_BACK:
-                if (!down) {
-                    mService.onBackPressed();
-                }
-                return true;
-            case KeyEvent.KEYCODE_MENU:
-                if (!down) {
-                    return mService.onMenuPressed();
-                }
-            case KeyEvent.KEYCODE_SPACE:
-                if (!down) {
-                    return mService.onSpacePressed();
-                }
-                break;
-            case KeyEvent.KEYCODE_VOLUME_DOWN:
-            case KeyEvent.KEYCODE_VOLUME_UP:
-                if (mService.isDozing()) {
-                    MediaSessionLegacyHelper.getHelper(mContext).sendVolumeKeyEvent(
-                            event, AudioManager.USE_DEFAULT_STREAM_TYPE, true);
-                    return true;
-                }
-                break;
-        }
-        return false;
+
+        return mInteractionEventHandler.dispatchKeyEvent(event);
     }
 
-    public void setTouchActive(boolean touchActive) {
-        mTouchActive = touchActive;
-    }
-
-    void suppressWakeUpGesture(boolean suppress) {
-        mSuppressingWakeUpGesture = suppress;
+    protected void setInteractionEventHandler(InteractionEventHandler listener) {
+        mInteractionEventHandler = listener;
     }
 
     @Override
     public boolean dispatchTouchEvent(MotionEvent ev) {
-        boolean isDown = ev.getActionMasked() == MotionEvent.ACTION_DOWN;
-        boolean isUp = ev.getActionMasked() == MotionEvent.ACTION_UP;
-        boolean isCancel = ev.getActionMasked() == MotionEvent.ACTION_CANCEL;
+        Boolean result = mInteractionEventHandler.handleDispatchTouchEvent(ev);
 
-        // Reset manual touch dispatch state here but make sure the UP/CANCEL event still gets
-        // delivered.
-        boolean expandingBelowNotch = mExpandingBelowNotch;
-        if (isUp || isCancel) {
-            mExpandingBelowNotch = false;
-        }
-
-        if (!isCancel && mService.shouldIgnoreTouch()) {
-            return false;
-        }
-        if (isDown && mNotificationPanel.isFullyCollapsed()) {
-            mNotificationPanel.startExpandLatencyTracking();
-        }
-        if (isDown) {
-            setTouchActive(true);
-            mTouchCancelled = false;
-        } else if (ev.getActionMasked() == MotionEvent.ACTION_UP
-                || ev.getActionMasked() == MotionEvent.ACTION_CANCEL) {
-            setTouchActive(false);
-        }
-        if (mTouchCancelled || mExpandAnimationRunning || mExpandAnimationPending) {
-            return false;
-        }
-        mFalsingManager.onTouchEvent(ev, getWidth(), getHeight());
-        mGestureDetector.onTouchEvent(ev);
-        if (mBrightnessMirror != null && mBrightnessMirror.getVisibility() == VISIBLE) {
-            // Disallow new pointers while the brightness mirror is visible. This is so that you
-            // can't touch anything other than the brightness slider while the mirror is showing
-            // and the rest of the panel is transparent.
-            if (ev.getActionMasked() == MotionEvent.ACTION_POINTER_DOWN) {
-                return false;
-            }
-        }
-        if (isDown) {
-            getStackScrollLayout().closeControlsIfOutsideTouch(ev);
-        }
-        if (mService.isDozing()) {
-            mService.mDozeScrimController.extendPulse();
-        }
-
-        // In case we start outside of the view bounds (below the status bar), we need to dispatch
-        // the touch manually as the view system can't accomodate for touches outside of the
-        // regular view bounds.
-        if (isDown && ev.getY() >= mBottom) {
-            mExpandingBelowNotch = true;
-            expandingBelowNotch = true;
-        }
-        if (expandingBelowNotch) {
-            return mStatusBarView.dispatchTouchEvent(ev);
-        }
-
-        return super.dispatchTouchEvent(ev);
+        return result != null ? result : super.dispatchTouchEvent(ev);
     }
 
     @Override
     public boolean onInterceptTouchEvent(MotionEvent ev) {
-        NotificationStackScrollLayout stackScrollLayout = getStackScrollLayout();
-        if (mService.isDozing() && !mService.isPulsing()) {
-            // Capture all touch events in always-on.
-            return true;
-        }
-        boolean intercept = false;
-        if (mNotificationPanel.isFullyExpanded()
-                && mDragDownHelper.isDragDownEnabled()
-                && !mService.isBouncerShowing()
-                && !mService.isDozing()) {
-            intercept = mDragDownHelper.onInterceptTouchEvent(ev);
-        }
+        boolean intercept = mInteractionEventHandler.shouldInterceptTouchEvent(ev);
         if (!intercept) {
-            super.onInterceptTouchEvent(ev);
+            intercept = super.onInterceptTouchEvent(ev);
         }
         if (intercept) {
-            MotionEvent cancellation = MotionEvent.obtain(ev);
-            cancellation.setAction(MotionEvent.ACTION_CANCEL);
-            stackScrollLayout.onInterceptTouchEvent(cancellation);
-            mNotificationPanel.onInterceptTouchEvent(cancellation);
-            cancellation.recycle();
+            mInteractionEventHandler.didIntercept(ev);
         }
+
         return intercept;
     }
 
     @Override
     public boolean onTouchEvent(MotionEvent ev) {
-        boolean handled = false;
-        if (mService.isDozing()) {
-            handled = !mService.isPulsing();
-        }
-        if ((mDragDownHelper.isDragDownEnabled() && !handled) || mDragDownHelper.isDraggingDown()) {
-            // we still want to finish our drag down gesture when locking the screen
-            handled = mDragDownHelper.onTouchEvent(ev);
-        }
+        boolean handled = mInteractionEventHandler.handleTouchEvent(ev);
+
         if (!handled) {
             handled = super.onTouchEvent(ev);
         }
-        final int action = ev.getAction();
-        if (!handled && (action == MotionEvent.ACTION_UP || action == MotionEvent.ACTION_CANCEL)) {
-            mService.setInteracting(StatusBarManager.WINDOW_STATUS_BAR, false);
+
+        if (!handled) {
+            mInteractionEventHandler.didNotHandleTouchEvent(ev);
         }
+
         return handled;
     }
 
@@ -465,77 +217,6 @@
         }
     }
 
-    public void cancelExpandHelper() {
-        NotificationStackScrollLayout stackScrollLayout = getStackScrollLayout();
-        if (stackScrollLayout != null) {
-            stackScrollLayout.cancelExpandHelper();
-        }
-    }
-
-    public void cancelCurrentTouch() {
-        if (mTouchActive) {
-            final long now = SystemClock.uptimeMillis();
-            MotionEvent event = MotionEvent.obtain(now, now,
-                    MotionEvent.ACTION_CANCEL, 0.0f, 0.0f, 0);
-            event.setSource(InputDevice.SOURCE_TOUCHSCREEN);
-            dispatchTouchEvent(event);
-            event.recycle();
-            mTouchCancelled = true;
-        }
-    }
-
-    public void setExpandAnimationRunning(boolean expandAnimationRunning) {
-        mExpandAnimationRunning = expandAnimationRunning;
-    }
-
-    public void setExpandAnimationPending(boolean pending) {
-        mExpandAnimationPending = pending;
-    }
-
-    public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
-        pw.print("  mExpandAnimationPending="); pw.println(mExpandAnimationPending);
-        pw.print("  mExpandAnimationRunning="); pw.println(mExpandAnimationRunning);
-        pw.print("  mTouchCancelled="); pw.println(mTouchCancelled);
-        pw.print("  mTouchActive="); pw.println(mTouchActive);
-    }
-
-    /**
-     * Called whenever the scrims become opaque, transparent or semi-transparent.
-     */
-    public void onScrimVisibilityChanged(@ScrimVisibility int scrimsVisible) {
-        if (mLockIcon != null) {
-            mLockIcon.onScrimVisibilityChanged(scrimsVisible);
-        }
-    }
-
-    /**
-     * When we're launching an affordance, like double pressing power to open camera.
-     */
-    public void onShowingLaunchAffordanceChanged(boolean showing) {
-        if (mLockIcon != null) {
-            mLockIcon.onShowingLaunchAffordanceChanged(showing);
-        }
-    }
-
-    public void setBypassController(KeyguardBypassController bypassController) {
-        mBypassController = bypassController;
-    }
-
-    public void setBouncerShowingScrimmed(boolean bouncerShowing) {
-        if (mLockIcon != null) {
-            mLockIcon.setBouncerShowingScrimmed(bouncerShowing);
-        }
-    }
-
-    /**
-     * When {@link KeyguardBouncer} starts to be dismissed and starts to play its animation.
-     */
-    public void onBouncerPreHideAnimation() {
-        if (mLockIcon != null) {
-            mLockIcon.onBouncerPreHideAnimation();
-        }
-    }
-
     public class LayoutParams extends FrameLayout.LayoutParams {
 
         public boolean ignoreRightInset;
@@ -657,6 +338,35 @@
         }
     }
 
+    interface InteractionEventHandler {
+        /**
+         * Returns a result for {@link ViewGroup#dispatchTouchEvent(MotionEvent)} or null to defer
+         * to the super method.
+         */
+        Boolean handleDispatchTouchEvent(MotionEvent ev);
+
+        /**
+         * Returns if the view should intercept the touch event.
+         *
+         * The touch event may still be interecepted if
+         * {@link ViewGroup#onInterceptTouchEvent(MotionEvent)} decides to do so.
+         */
+        boolean shouldInterceptTouchEvent(MotionEvent ev);
+
+        /**
+         * Called when the view decides to intercept the touch event.
+         */
+        void didIntercept(MotionEvent ev);
+
+        boolean handleTouchEvent(MotionEvent ev);
+
+        void didNotHandleTouchEvent(MotionEvent ev);
+
+        boolean interceptMediaKey(KeyEvent event);
+
+        boolean dispatchKeyEvent(KeyEvent event);
+    }
+
     /**
      * Minimal window to satisfy FloatingToolbar.
      */
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowViewController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowViewController.java
new file mode 100644
index 0000000..1ce7763
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowViewController.java
@@ -0,0 +1,558 @@
+/*
+ * 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 android.app.StatusBarManager;
+import android.hardware.display.AmbientDisplayConfiguration;
+import android.media.AudioManager;
+import android.media.session.MediaSessionLegacyHelper;
+import android.os.SystemClock;
+import android.os.UserHandle;
+import android.provider.Settings;
+import android.view.GestureDetector;
+import android.view.InputDevice;
+import android.view.KeyEvent;
+import android.view.LayoutInflater;
+import android.view.MotionEvent;
+import android.view.View;
+import android.view.ViewGroup;
+import android.view.ViewStub;
+
+import com.android.internal.annotations.VisibleForTesting;
+import com.android.systemui.ExpandHelper;
+import com.android.systemui.R;
+import com.android.systemui.doze.DozeLog;
+import com.android.systemui.plugins.FalsingManager;
+import com.android.systemui.plugins.statusbar.StatusBarStateController;
+import com.android.systemui.shared.plugins.PluginManager;
+import com.android.systemui.statusbar.DragDownHelper;
+import com.android.systemui.statusbar.NotificationLockscreenUserManager;
+import com.android.systemui.statusbar.PulseExpansionHandler;
+import com.android.systemui.statusbar.SysuiStatusBarStateController;
+import com.android.systemui.statusbar.notification.DynamicPrivacyController;
+import com.android.systemui.statusbar.notification.NotificationEntryManager;
+import com.android.systemui.statusbar.notification.NotificationWakeUpCoordinator;
+import com.android.systemui.statusbar.notification.stack.NotificationStackScrollLayout;
+import com.android.systemui.statusbar.policy.KeyguardStateController;
+import com.android.systemui.tuner.TunerService;
+import com.android.systemui.util.InjectionInflationController;
+
+import java.io.FileDescriptor;
+import java.io.PrintWriter;
+
+import javax.inject.Inject;
+
+/**
+ * Controller for {@link StatusBarWindowView}.
+ */
+public class StatusBarWindowViewController {
+    private final StatusBarWindowView mView;
+    private final FalsingManager mFalsingManager;
+    private final GestureDetector mGestureDetector;
+    private View mBrightnessMirror;
+    private boolean mTouchActive;
+    private boolean mTouchCancelled;
+    private boolean mExpandAnimationPending;
+    private boolean mExpandAnimationRunning;
+    private NotificationStackScrollLayout mStackScrollLayout;
+    private LockIcon mLockIcon;
+    private PhoneStatusBarView mStatusBarView;
+    private StatusBar mService;
+    private DragDownHelper mDragDownHelper;
+    private boolean mSuppressingWakeUpGesture;
+    private boolean mDoubleTapEnabled;
+    private boolean mSingleTapEnabled;
+    private boolean mExpandingBelowNotch;
+
+    private StatusBarWindowViewController(
+            StatusBarWindowView view,
+            InjectionInflationController injectionInflationController,
+            NotificationWakeUpCoordinator coordinator,
+            PulseExpansionHandler pulseExpansionHandler,
+            DynamicPrivacyController dynamicPrivacyController,
+            KeyguardBypassController bypassController,
+            FalsingManager falsingManager,
+            PluginManager pluginManager,
+            TunerService tunerService,
+            ShadeController shadeController,
+            NotificationLockscreenUserManager notificationLockscreenUserManager,
+            NotificationEntryManager notificationEntryManager,
+            KeyguardStateController keyguardStateController,
+            SysuiStatusBarStateController statusBarStateController,
+            DozeLog dozeLog) {
+        mView = view;
+        mFalsingManager = falsingManager;
+
+        // TODO: create controller for NotificationPanelView
+        NotificationPanelView notificationPanelView = new NotificationPanelView(
+                view.getContext(),
+                null,
+                injectionInflationController,
+                coordinator,
+                pulseExpansionHandler,
+                dynamicPrivacyController,
+                bypassController,
+                falsingManager,
+                pluginManager,
+                shadeController,
+                notificationLockscreenUserManager,
+                notificationEntryManager,
+                keyguardStateController,
+                statusBarStateController,
+                dozeLog);
+        ViewGroup.LayoutParams lp = new ViewGroup.LayoutParams(
+                ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT);
+        notificationPanelView.setVisibility(View.INVISIBLE);
+        notificationPanelView.setId(R.id.notification_panel);
+        LayoutInflater li = injectionInflationController.injectable(
+                LayoutInflater.from(mView.getContext()));
+
+        li.inflate(R.layout.status_bar_expanded, notificationPanelView);
+        notificationPanelView.onChildrenAttached();
+
+        ViewStub statusBarExpanded = view.findViewById(R.id.status_bar_expanded);
+        mView.addView(notificationPanelView, mView.indexOfChild(statusBarExpanded), lp);
+        mView.removeView(statusBarExpanded);
+
+        mStackScrollLayout = mView.findViewById(R.id.notification_stack_scroller);
+        mLockIcon = mView.findViewById(R.id.lock_icon);
+        mBrightnessMirror = mView.findViewById(R.id.brightness_mirror);
+
+        TunerService.Tunable tunable = (key, newValue) -> {
+            AmbientDisplayConfiguration configuration =
+                    new AmbientDisplayConfiguration(mView.getContext());
+            switch (key) {
+                case Settings.Secure.DOZE_DOUBLE_TAP_GESTURE:
+                    mDoubleTapEnabled = configuration.doubleTapGestureEnabled(
+                            UserHandle.USER_CURRENT);
+                    break;
+                case Settings.Secure.DOZE_TAP_SCREEN_GESTURE:
+                    mSingleTapEnabled = configuration.tapGestureEnabled(UserHandle.USER_CURRENT);
+            }
+        };
+        tunerService.addTunable(tunable,
+                Settings.Secure.DOZE_DOUBLE_TAP_GESTURE,
+                Settings.Secure.DOZE_TAP_SCREEN_GESTURE);
+
+        GestureDetector.SimpleOnGestureListener gestureListener =
+                new GestureDetector.SimpleOnGestureListener() {
+                    @Override
+                    public boolean onSingleTapConfirmed(MotionEvent e) {
+                        if (mSingleTapEnabled && !mSuppressingWakeUpGesture) {
+                            mService.wakeUpIfDozing(
+                                    SystemClock.uptimeMillis(), mView, "SINGLE_TAP");
+                            return true;
+                        }
+                        return false;
+                    }
+
+                    @Override
+                    public boolean onDoubleTap(MotionEvent e) {
+                        if (mDoubleTapEnabled || mSingleTapEnabled) {
+                            mService.wakeUpIfDozing(
+                                    SystemClock.uptimeMillis(), mView, "DOUBLE_TAP");
+                            return true;
+                        }
+                        return false;
+                    }
+                };
+        mGestureDetector = new GestureDetector(mView.getContext(), gestureListener);
+
+        mView.setInteractionEventHandler(new StatusBarWindowView.InteractionEventHandler() {
+            @Override
+            public Boolean handleDispatchTouchEvent(MotionEvent ev) {
+                boolean isDown = ev.getActionMasked() == MotionEvent.ACTION_DOWN;
+                boolean isUp = ev.getActionMasked() == MotionEvent.ACTION_UP;
+                boolean isCancel = ev.getActionMasked() == MotionEvent.ACTION_CANCEL;
+
+                if (isUp || isCancel) {
+                    mExpandingBelowNotch = false;
+                }
+
+                // Reset manual touch dispatch state here but make sure the UP/CANCEL event still
+                // gets
+                // delivered.
+
+                if (!isCancel && mService.shouldIgnoreTouch()) {
+                    return false;
+                }
+                if (isDown && notificationPanelView.isFullyCollapsed()) {
+                    notificationPanelView.startExpandLatencyTracking();
+                }
+                if (isDown) {
+                    setTouchActive(true);
+                    mTouchCancelled = false;
+                } else if (ev.getActionMasked() == MotionEvent.ACTION_UP
+                        || ev.getActionMasked() == MotionEvent.ACTION_CANCEL) {
+                    setTouchActive(false);
+                }
+                if (mTouchCancelled || mExpandAnimationRunning || mExpandAnimationPending) {
+                    return false;
+                }
+                mFalsingManager.onTouchEvent(ev, mView.getWidth(), mView.getHeight());
+                mGestureDetector.onTouchEvent(ev);
+                if (mBrightnessMirror != null
+                        && mBrightnessMirror.getVisibility() == View.VISIBLE) {
+                    // Disallow new pointers while the brightness mirror is visible. This is so that
+                    // you can't touch anything other than the brightness slider while the mirror is
+                    // showing and the rest of the panel is transparent.
+                    if (ev.getActionMasked() == MotionEvent.ACTION_POINTER_DOWN) {
+                        return false;
+                    }
+                }
+                if (isDown) {
+                    getStackScrollLayout().closeControlsIfOutsideTouch(ev);
+                }
+                if (mService.isDozing()) {
+                    mService.mDozeScrimController.extendPulse();
+                }
+                // In case we start outside of the view bounds (below the status bar), we need to
+                // dispatch
+                // the touch manually as the view system can't accommodate for touches outside of
+                // the
+                // regular view bounds.
+                if (isDown && ev.getY() >= mView.getBottom()) {
+                    mExpandingBelowNotch = true;
+                }
+                if (mExpandingBelowNotch) {
+                    return mStatusBarView.dispatchTouchEvent(ev);
+                }
+
+                return null;
+            }
+
+            @Override
+            public boolean shouldInterceptTouchEvent(MotionEvent ev) {
+                if (mService.isDozing() && !mService.isPulsing()) {
+                    // Capture all touch events in always-on.
+                    return true;
+                }
+                boolean intercept = false;
+                if (notificationPanelView.isFullyExpanded()
+                        && mDragDownHelper.isDragDownEnabled()
+                        && !mService.isBouncerShowing()
+                        && !mService.isDozing()) {
+                    intercept = mDragDownHelper.onInterceptTouchEvent(ev);
+                }
+
+                return intercept;
+
+            }
+
+            @Override
+            public void didIntercept(MotionEvent ev) {
+                NotificationStackScrollLayout stackScrollLayout = getStackScrollLayout();
+                MotionEvent cancellation = MotionEvent.obtain(ev);
+                cancellation.setAction(MotionEvent.ACTION_CANCEL);
+                stackScrollLayout.onInterceptTouchEvent(cancellation);
+                notificationPanelView.onInterceptTouchEvent(cancellation);
+                cancellation.recycle();
+            }
+
+            @Override
+            public boolean handleTouchEvent(MotionEvent ev) {
+                boolean handled = false;
+                if (mService.isDozing()) {
+                    handled = !mService.isPulsing();
+                }
+                if ((mDragDownHelper.isDragDownEnabled() && !handled)
+                        || mDragDownHelper.isDraggingDown()) {
+                    // we still want to finish our drag down gesture when locking the screen
+                    handled = mDragDownHelper.onTouchEvent(ev);
+                }
+
+                return handled;
+            }
+
+            @Override
+            public void didNotHandleTouchEvent(MotionEvent ev) {
+                final int action = ev.getActionMasked();
+                if (action == MotionEvent.ACTION_UP || action == MotionEvent.ACTION_CANCEL) {
+                    mService.setInteracting(StatusBarManager.WINDOW_STATUS_BAR, false);
+                }
+            }
+
+            @Override
+            public boolean interceptMediaKey(KeyEvent event) {
+                return mService.interceptMediaKey(event);
+            }
+
+            @Override
+            public boolean dispatchKeyEvent(KeyEvent event) {
+                boolean down = event.getAction() == KeyEvent.ACTION_DOWN;
+                switch (event.getKeyCode()) {
+                    case KeyEvent.KEYCODE_BACK:
+                        if (!down) {
+                            mService.onBackPressed();
+                        }
+                        return true;
+                    case KeyEvent.KEYCODE_MENU:
+                        if (!down) {
+                            return mService.onMenuPressed();
+                        }
+                        break;
+                    case KeyEvent.KEYCODE_SPACE:
+                        if (!down) {
+                            return mService.onSpacePressed();
+                        }
+                        break;
+                    case KeyEvent.KEYCODE_VOLUME_DOWN:
+                    case KeyEvent.KEYCODE_VOLUME_UP:
+                        if (mService.isDozing()) {
+                            MediaSessionLegacyHelper.getHelper(mView.getContext())
+                                    .sendVolumeKeyEvent(
+                                            event, AudioManager.USE_DEFAULT_STREAM_TYPE, true);
+                            return true;
+                        }
+                        break;
+                }
+                return false;
+            }
+        });
+
+        mView.setOnHierarchyChangeListener(new ViewGroup.OnHierarchyChangeListener() {
+            @Override
+            public void onChildViewAdded(View parent, View child) {
+                if (child.getId() == R.id.brightness_mirror) {
+                    mBrightnessMirror = child;
+                }
+            }
+
+            @Override
+            public void onChildViewRemoved(View parent, View child) {
+            }
+        });
+    }
+
+    public StatusBarWindowView getView() {
+        return mView;
+    }
+
+    public void setTouchActive(boolean touchActive) {
+        mTouchActive = touchActive;
+    }
+
+    public void cancelCurrentTouch() {
+        if (mTouchActive) {
+            final long now = SystemClock.uptimeMillis();
+            MotionEvent event = MotionEvent.obtain(now, now,
+                    MotionEvent.ACTION_CANCEL, 0.0f, 0.0f, 0);
+            event.setSource(InputDevice.SOURCE_TOUCHSCREEN);
+            mView.dispatchTouchEvent(event);
+            event.recycle();
+            mTouchCancelled = true;
+        }
+    }
+
+    public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
+        pw.print("  mExpandAnimationPending=");
+        pw.println(mExpandAnimationPending);
+        pw.print("  mExpandAnimationRunning=");
+        pw.println(mExpandAnimationRunning);
+        pw.print("  mTouchCancelled=");
+        pw.println(mTouchCancelled);
+        pw.print("  mTouchActive=");
+        pw.println(mTouchActive);
+    }
+
+    public void setExpandAnimationPending(boolean pending) {
+        mExpandAnimationPending = pending;
+    }
+
+    public void setExpandAnimationRunning(boolean running) {
+        mExpandAnimationRunning = running;
+    }
+
+    public void cancelExpandHelper() {
+        NotificationStackScrollLayout stackScrollLayout = getStackScrollLayout();
+        if (stackScrollLayout != null) {
+            stackScrollLayout.cancelExpandHelper();
+        }
+    }
+
+    @VisibleForTesting
+    protected NotificationStackScrollLayout getStackScrollLayout() {
+        return mStackScrollLayout;
+    }
+
+    /**
+     * Called whenever the scrims become opaque, transparent or semi-transparent.
+     */
+    public void onScrimVisibilityChanged(Integer scrimsVisible) {
+        if (mLockIcon != null) {
+            mLockIcon.onScrimVisibilityChanged(scrimsVisible);
+        }
+    }
+
+    /**
+     * Propagate {@link StatusBar} pulsing state.
+     */
+    public void setPulsing(boolean pulsing) {
+        if (mLockIcon != null) {
+            mLockIcon.setPulsing(pulsing);
+        }
+    }
+
+    /**
+     * Called when the biometric authentication mode changes.
+     *
+     * @param wakeAndUnlock If the type is {@link BiometricUnlockController#isWakeAndUnlock()}
+     * @param isUnlock      If the type is {@link BiometricUnlockController#isBiometricUnlock()} ()
+     */
+    public void onBiometricAuthModeChanged(boolean wakeAndUnlock, boolean isUnlock) {
+        if (mLockIcon != null) {
+            mLockIcon.onBiometricAuthModeChanged(wakeAndUnlock, isUnlock);
+        }
+    }
+
+    public void setStatusBarView(PhoneStatusBarView statusBarView) {
+        mStatusBarView = statusBarView;
+    }
+
+    public void setService(StatusBar statusBar) {
+        mService = statusBar;
+        NotificationStackScrollLayout stackScrollLayout = getStackScrollLayout();
+        ExpandHelper.Callback expandHelperCallback = stackScrollLayout.getExpandHelperCallback();
+        DragDownHelper.DragDownCallback dragDownCallback = stackScrollLayout.getDragDownCallback();
+        setDragDownHelper(
+                new DragDownHelper(
+                        mView.getContext(), mView, expandHelperCallback,
+                        dragDownCallback, mFalsingManager));
+    }
+
+    @VisibleForTesting
+    void setDragDownHelper(DragDownHelper dragDownHelper) {
+        mDragDownHelper = dragDownHelper;
+    }
+
+    public void suppressWakeUpGesture(boolean suppress) {
+        mSuppressingWakeUpGesture = suppress;
+    }
+
+    /**
+     * When we're launching an affordance, like double pressing power to open camera.
+     */
+    public void onShowingLaunchAffordanceChanged(Boolean showing) {
+        if (mLockIcon != null) {
+            mLockIcon.onShowingLaunchAffordanceChanged(showing);
+        }
+    }
+
+    public void setBouncerShowingScrimmed(boolean bouncerShowing) {
+        if (mLockIcon != null) {
+            mLockIcon.setBouncerShowingScrimmed(bouncerShowing);
+        }
+    }
+
+    /**
+     * When {@link KeyguardBouncer} starts to be dismissed and starts to play its animation.
+     */
+    public void onBouncerPreHideAnimation() {
+        if (mLockIcon != null) {
+            mLockIcon.onBouncerPreHideAnimation();
+        }
+    }
+
+    /**
+     * Builder for {@link StatusBarWindowViewController}.
+     */
+    public static class Builder {
+        private final InjectionInflationController mInjectionInflationController;
+        private final NotificationWakeUpCoordinator mCoordinator;
+        private final PulseExpansionHandler mPulseExpansionHandler;
+        private final DynamicPrivacyController mDynamicPrivacyController;
+        private final KeyguardBypassController mBypassController;
+        private final FalsingManager mFalsingManager;
+        private final PluginManager mPluginManager;
+        private final TunerService mTunerService;
+        private final KeyguardStateController mKeyguardStateController;
+        private final SysuiStatusBarStateController mStatusBarStateController;
+        private ShadeController mShadeController;
+        private final NotificationLockscreenUserManager mNotificationLockScreenUserManager;
+        private final NotificationEntryManager mNotificationEntryManager;
+        private final DozeLog mDozeLog;
+        private StatusBarWindowView mView;
+
+        @Inject
+        public Builder(
+                InjectionInflationController injectionInflationController,
+                NotificationWakeUpCoordinator coordinator,
+                PulseExpansionHandler pulseExpansionHandler,
+                DynamicPrivacyController dynamicPrivacyController,
+                KeyguardBypassController bypassController,
+                FalsingManager falsingManager,
+                PluginManager pluginManager,
+                TunerService tunerService,
+                NotificationLockscreenUserManager notificationLockscreenUserManager,
+                NotificationEntryManager notificationEntryManager,
+                KeyguardStateController keyguardStateController,
+                StatusBarStateController statusBarStateController,
+                DozeLog dozeLog) {
+            mInjectionInflationController = injectionInflationController;
+            mCoordinator = coordinator;
+            mPulseExpansionHandler = pulseExpansionHandler;
+            mDynamicPrivacyController = dynamicPrivacyController;
+            mBypassController = bypassController;
+            mFalsingManager = falsingManager;
+            mPluginManager = pluginManager;
+            mTunerService = tunerService;
+            mNotificationLockScreenUserManager = notificationLockscreenUserManager;
+            mNotificationEntryManager = notificationEntryManager;
+            mKeyguardStateController = keyguardStateController;
+            mStatusBarStateController = (SysuiStatusBarStateController) statusBarStateController;
+            mDozeLog = dozeLog;
+        }
+
+        /**
+         * Provide {@link StatusBarWindowView} to attach this controller to.
+         */
+        public Builder setStatusBarWindowView(StatusBarWindowView view) {
+            mView = view;
+            return this;
+        }
+
+        /**
+         * Provide {@link ShadeController} that this view needs.
+         */
+        public Builder setShadeController(ShadeController shadeController) {
+            mShadeController = shadeController;
+            return this;
+        }
+
+        /**
+         * Build a {@link StatusBarWindowView}.
+         */
+        public StatusBarWindowViewController build() {
+            return new StatusBarWindowViewController(
+                    mView,
+                    mInjectionInflationController,
+                    mCoordinator,
+                    mPulseExpansionHandler,
+                    mDynamicPrivacyController,
+                    mBypassController,
+                    mFalsingManager,
+                    mPluginManager,
+                    mTunerService,
+                    mShadeController,
+                    mNotificationLockScreenUserManager,
+                    mNotificationEntryManager,
+                    mKeyguardStateController,
+                    mStatusBarStateController,
+                    mDozeLog);
+        }
+    }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyguardStateController.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyguardStateController.java
index aefe201..692c34c 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyguardStateController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyguardStateController.java
@@ -146,7 +146,7 @@
     /** **/
     default void notifyKeyguardDoneFading() {}
     /** **/
-    default void notifyKeyguardState(boolean showing, boolean methodSecure, boolean occluded) {}
+    default void notifyKeyguardState(boolean showing, boolean occluded) {}
 
     /**
      * Callback for authentication events.
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyguardStateControllerImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyguardStateControllerImpl.java
index cc91bc0..1cb2bd4 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyguardStateControllerImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyguardStateControllerImpl.java
@@ -25,11 +25,12 @@
 import android.os.Build;
 import android.os.Trace;
 
+import androidx.annotation.VisibleForTesting;
+
 import com.android.internal.util.Preconditions;
 import com.android.internal.widget.LockPatternUtils;
 import com.android.keyguard.KeyguardUpdateMonitor;
 import com.android.keyguard.KeyguardUpdateMonitorCallback;
-import com.android.systemui.Dependency;
 import com.android.systemui.Dumpable;
 
 import java.io.FileDescriptor;
@@ -42,25 +43,22 @@
 /**
  */
 @Singleton
-public class KeyguardStateControllerImpl extends KeyguardUpdateMonitorCallback
-        implements KeyguardStateController, Dumpable {
+public class KeyguardStateControllerImpl implements KeyguardStateController, Dumpable {
 
     private static final boolean DEBUG_AUTH_WITH_ADB = false;
     private static final String AUTH_BROADCAST_KEY = "debug_trigger_auth";
 
     private final ArrayList<Callback> mCallbacks = new ArrayList<>();
-    private final Context mContext;
     private final KeyguardUpdateMonitor mKeyguardUpdateMonitor;
     private final LockPatternUtils mLockPatternUtils;
     private final KeyguardUpdateMonitorCallback mKeyguardUpdateMonitorCallback =
-            new LockedStateInvalidator();
+            new UpdateMonitorCallback();
 
     private boolean mCanDismissLockScreen;
     private boolean mShowing;
     private boolean mSecure;
     private boolean mOccluded;
 
-    private boolean mListening;
     private boolean mKeyguardFadingAway;
     private long mKeyguardFadingAwayDelay;
     private long mKeyguardFadingAwayDuration;
@@ -75,10 +73,10 @@
     /**
      */
     @Inject
-    public KeyguardStateControllerImpl(Context context) {
-        mContext = context;
-        mKeyguardUpdateMonitor = Dependency.get(KeyguardUpdateMonitor.class);
-        mLockPatternUtils = new LockPatternUtils(context);
+    public KeyguardStateControllerImpl(Context context,
+            KeyguardUpdateMonitor keyguardUpdateMonitor, LockPatternUtils lockPatternUtils) {
+        mKeyguardUpdateMonitor = keyguardUpdateMonitor;
+        mLockPatternUtils = lockPatternUtils;
         mKeyguardUpdateMonitor.registerCallback(mKeyguardUpdateMonitorCallback);
 
         update(true /* updateAlways */);
@@ -104,19 +102,12 @@
         if (!mCallbacks.contains(callback)) {
             mCallbacks.add(callback);
         }
-        if (mCallbacks.size() != 0 && !mListening) {
-            mListening = true;
-            mKeyguardUpdateMonitor.registerCallback(this);
-        }
     }
 
     @Override
     public void removeCallback(@NonNull Callback callback) {
         Preconditions.checkNotNull(callback, "Callback must not be null. b/128895449");
-        if (mCallbacks.remove(callback) && mCallbacks.size() == 0 && mListening) {
-            mListening = false;
-            mKeyguardUpdateMonitor.removeCallback(this);
-        }
+        mCallbacks.remove(callback);
     }
 
     @Override
@@ -140,27 +131,25 @@
     }
 
     @Override
-    public void notifyKeyguardState(boolean showing, boolean secure, boolean occluded) {
-        if (mShowing == showing && mSecure == secure && mOccluded == occluded) return;
+    public void notifyKeyguardState(boolean showing, boolean occluded) {
+        if (mShowing == showing && mOccluded == occluded) return;
         mShowing = showing;
-        mSecure = secure;
         mOccluded = occluded;
         notifyKeyguardChanged();
     }
 
-    @Override
-    public void onTrustChanged(int userId) {
-        notifyKeyguardChanged();
-    }
-
     private void notifyKeyguardChanged() {
+        Trace.beginSection("KeyguardStateController#notifyKeyguardChanged");
         // Copy the list to allow removal during callback.
         new ArrayList<>(mCallbacks).forEach(Callback::onKeyguardShowingChanged);
+        Trace.endSection();
     }
 
     private void notifyUnlockedChanged() {
+        Trace.beginSection("KeyguardStateController#notifyUnlockedChanged");
         // Copy the list to allow removal during callback.
         new ArrayList<>(mCallbacks).forEach(Callback::onUnlockedChanged);
+        Trace.endSection();
     }
 
     @Override
@@ -187,7 +176,8 @@
         setKeyguardFadingAway(false);
     }
 
-    private void update(boolean updateAlways) {
+    @VisibleForTesting
+    void update(boolean updateAlways) {
         Trace.beginSection("KeyguardStateController#update");
         int user = KeyguardUpdateMonitor.getCurrentUser();
         boolean secure = mLockPatternUtils.isSecure(user);
@@ -197,7 +187,7 @@
         boolean trusted = mKeyguardUpdateMonitor.getUserHasTrust(user);
         boolean faceAuthEnabled = mKeyguardUpdateMonitor.isFaceAuthEnabledForUser(user);
         boolean changed = secure != mSecure || canDismissLockScreen != mCanDismissLockScreen
-                || trustManaged != mTrustManaged
+                || trustManaged != mTrustManaged || mTrusted != trusted
                 || mFaceAuthEnabled != faceAuthEnabled;
         if (changed || updateAlways) {
             mSecure = secure;
@@ -280,7 +270,7 @@
         pw.println("  mFaceAuthEnabled: " + mFaceAuthEnabled);
     }
 
-    private class LockedStateInvalidator extends KeyguardUpdateMonitorCallback {
+    private class UpdateMonitorCallback extends KeyguardUpdateMonitorCallback {
         @Override
         public void onUserSwitchComplete(int userId) {
             update(false /* updateAlways */);
@@ -289,6 +279,7 @@
         @Override
         public void onTrustChanged(int userId) {
             update(false /* updateAlways */);
+            notifyKeyguardChanged();
         }
 
         @Override
@@ -323,11 +314,6 @@
         }
 
         @Override
-        public void onScreenTurnedOff() {
-            update(false /* updateAlways */);
-        }
-
-        @Override
         public void onKeyguardVisibilityChanged(boolean showing) {
             update(false /* updateAlways */);
         }
@@ -336,5 +322,5 @@
         public void onBiometricsCleared() {
             update(false /* alwaysUpdate */);
         }
-    };
+    }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/tv/TvStatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/tv/TvStatusBar.java
index b80b6d5..c2ed7df 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/tv/TvStatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/tv/TvStatusBar.java
@@ -36,6 +36,10 @@
  */
 public class TvStatusBar extends SystemUI implements CommandQueue.Callbacks {
 
+    public TvStatusBar(Context context) {
+        super(context);
+    }
+
     @Override
     public void start() {
         putComponent(TvStatusBar.class, this);
diff --git a/packages/SystemUI/src/com/android/systemui/theme/ThemeOverlayController.java b/packages/SystemUI/src/com/android/systemui/theme/ThemeOverlayController.java
index 89aa797..9a58a35 100644
--- a/packages/SystemUI/src/com/android/systemui/theme/ThemeOverlayController.java
+++ b/packages/SystemUI/src/com/android/systemui/theme/ThemeOverlayController.java
@@ -61,6 +61,10 @@
     private ThemeOverlayManager mThemeManager;
     private UserManager mUserManager;
 
+    public ThemeOverlayController(Context context) {
+        super(context);
+    }
+
     @Override
     public void start() {
         if (DEBUG) Log.d(TAG, "Start");
diff --git a/packages/SystemUI/src/com/android/systemui/usb/StorageNotification.java b/packages/SystemUI/src/com/android/systemui/usb/StorageNotification.java
index ff5bd03..11885c5 100644
--- a/packages/SystemUI/src/com/android/systemui/usb/StorageNotification.java
+++ b/packages/SystemUI/src/com/android/systemui/usb/StorageNotification.java
@@ -60,6 +60,10 @@
     private NotificationManager mNotificationManager;
     private StorageManager mStorageManager;
 
+    public StorageNotification(Context context) {
+        super(context);
+    }
+
     private static class MoveInfo {
         public int moveId;
         public Bundle extras;
diff --git a/packages/SystemUI/src/com/android/systemui/usb/UsbPermissionActivity.java b/packages/SystemUI/src/com/android/systemui/usb/UsbPermissionActivity.java
index a46f018..47b56e0 100644
--- a/packages/SystemUI/src/com/android/systemui/usb/UsbPermissionActivity.java
+++ b/packages/SystemUI/src/com/android/systemui/usb/UsbPermissionActivity.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.ApplicationInfo;
 import android.content.pm.PackageManager;
 import android.hardware.usb.IUsbManager;
@@ -84,14 +85,27 @@
         final AlertController.AlertParams ap = mAlertParams;
         ap.mTitle = appName;
         if (mDevice == null) {
+            // Accessory Case
+
             ap.mMessage = getString(R.string.usb_accessory_permission_prompt, appName,
                     mAccessory.getDescription());
             mDisconnectedReceiver = new UsbDisconnectedReceiver(this, mAccessory);
         } else {
-            ap.mMessage = getString(R.string.usb_device_permission_prompt, appName,
-                    mDevice.getProductName());
+            boolean hasRecordPermission =
+                    PermissionChecker.checkPermissionForPreflight(
+                            this, android.Manifest.permission.RECORD_AUDIO, -1, aInfo.uid,
+                            mPackageName)
+                            == android.content.pm.PackageManager.PERMISSION_GRANTED;
+            boolean isAudioCaptureDevice = mDevice.getHasAudioCapture();
+            boolean useRecordWarning = isAudioCaptureDevice && !hasRecordPermission;
+
+            int strID = useRecordWarning
+                    ? R.string.usb_device_permission_prompt_warn
+                    : R.string.usb_device_permission_prompt;
+            ap.mMessage = getString(strID, appName, mDevice.getProductName());
             mDisconnectedReceiver = new UsbDisconnectedReceiver(this, mDevice);
         }
+
         ap.mPositiveButtonText = getString(android.R.string.ok);
         ap.mNegativeButtonText = getString(android.R.string.cancel);
         ap.mPositiveButtonListener = this;
diff --git a/packages/SystemUI/src/com/android/systemui/util/NotificationChannels.java b/packages/SystemUI/src/com/android/systemui/util/NotificationChannels.java
index f35af90..8c60747 100644
--- a/packages/SystemUI/src/com/android/systemui/util/NotificationChannels.java
+++ b/packages/SystemUI/src/com/android/systemui/util/NotificationChannels.java
@@ -38,6 +38,10 @@
     public static String BATTERY     = "BAT";
     public static String HINTS       = "HNT";
 
+    public NotificationChannels(Context context) {
+        super(context);
+    }
+
     public static void createAll(Context context) {
         final NotificationManager nm = context.getSystemService(NotificationManager.class);
         final NotificationChannel batteryChannel = new NotificationChannel(BATTERY,
diff --git a/packages/SystemUI/src/com/android/systemui/util/leak/DumpTruck.java b/packages/SystemUI/src/com/android/systemui/util/leak/DumpTruck.java
index fa7af0b..be5e0a0 100644
--- a/packages/SystemUI/src/com/android/systemui/util/leak/DumpTruck.java
+++ b/packages/SystemUI/src/com/android/systemui/util/leak/DumpTruck.java
@@ -36,6 +36,7 @@
 import java.io.InputStream;
 import java.util.ArrayList;
 import java.util.Arrays;
+import java.util.List;
 import java.util.zip.ZipEntry;
 import java.util.zip.ZipOutputStream;
 
@@ -53,7 +54,7 @@
 
     private final Context context;
     private Uri hprofUri;
-    private long pss;
+    private long rss;
     final StringBuilder body = new StringBuilder();
 
     public DumpTruck(Context context) {
@@ -66,7 +67,7 @@
      * @param pids
      * @return this, for chaining
      */
-    public DumpTruck captureHeaps(int[] pids) {
+    public DumpTruck captureHeaps(List<Long> pids) {
         final GarbageMonitor gm = Dependency.get(GarbageMonitor.class);
 
         final File dumpDir = new File(context.getCacheDir(), FILEPROVIDER_PATH);
@@ -79,8 +80,8 @@
         final ArrayList<String> paths = new ArrayList<String>();
         final int myPid = android.os.Process.myPid();
 
-        final int[] pids_copy = Arrays.copyOf(pids, pids.length);
-        for (int pid : pids_copy) {
+        for (Long pidL : pids) {
+            final int pid = pidL.intValue();
             body.append("  pid ").append(pid);
             if (gm != null) {
                 GarbageMonitor.ProcessMemInfo info = gm.getMemInfo(pid);
@@ -88,11 +89,9 @@
                     body.append(":")
                             .append(" up=")
                             .append(info.getUptime())
-                            .append(" pss=")
-                            .append(info.currentPss)
-                            .append(" uss=")
-                            .append(info.currentUss);
-                    pss = info.currentPss;
+                            .append(" rss=")
+                            .append(info.currentRss);
+                    rss = info.currentRss;
                 }
             }
             if (pid == myPid) {
@@ -147,7 +146,7 @@
         shareIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
         shareIntent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
         shareIntent.putExtra(Intent.EXTRA_SUBJECT,
-                String.format("SystemUI memory dump (pss=%dM)", pss / 1024));
+                String.format("SystemUI memory dump (rss=%dM)", rss / 1024));
 
         shareIntent.putExtra(Intent.EXTRA_TEXT, body.toString());
 
diff --git a/packages/SystemUI/src/com/android/systemui/util/leak/GarbageMonitor.java b/packages/SystemUI/src/com/android/systemui/util/leak/GarbageMonitor.java
index db43906..63db755 100644
--- a/packages/SystemUI/src/com/android/systemui/util/leak/GarbageMonitor.java
+++ b/packages/SystemUI/src/com/android/systemui/util/leak/GarbageMonitor.java
@@ -35,7 +35,6 @@
 import android.graphics.Rect;
 import android.graphics.drawable.Drawable;
 import android.os.Build;
-import android.os.Debug;
 import android.os.Handler;
 import android.os.Looper;
 import android.os.Message;
@@ -57,6 +56,7 @@
 import java.io.FileDescriptor;
 import java.io.PrintWriter;
 import java.util.ArrayList;
+import java.util.List;
 
 import javax.inject.Inject;
 import javax.inject.Named;
@@ -102,7 +102,6 @@
 
     private final LongSparseArray<ProcessMemInfo> mData = new LongSparseArray<>();
     private final ArrayList<Long> mPids = new ArrayList<>();
-    private int[] mPidsArray = new int[1];
 
     private long mHeapLimit;
 
@@ -164,8 +163,8 @@
         return mData.get(pid);
     }
 
-    public int[] getTrackedProcesses() {
-        return mPidsArray;
+    public List<Long> getTrackedProcesses() {
+        return mPids;
     }
 
     public void startTrackingProcess(long pid, String name, long start) {
@@ -173,43 +172,40 @@
             if (mPids.contains(pid)) return;
 
             mPids.add(pid);
-            updatePidsArrayL();
+            logPids();
 
             mData.put(pid, new ProcessMemInfo(pid, name, start));
         }
     }
 
-    private void updatePidsArrayL() {
-        final int N = mPids.size();
-        mPidsArray = new int[N];
-        StringBuffer sb = new StringBuffer("Now tracking processes: ");
-        for (int i = 0; i < N; i++) {
-            final int p = mPids.get(i).intValue();
-            mPidsArray[i] = p;
-            sb.append(p);
-            sb.append(" ");
+    private void logPids() {
+        if (DEBUG) {
+            StringBuffer sb = new StringBuffer("Now tracking processes: ");
+            for (int i = 0; i < mPids.size(); i++) {
+                final int p = mPids.get(i).intValue();
+                sb.append(" ");
+            }
+            Log.v(TAG, sb.toString());
         }
-        if (DEBUG) Log.v(TAG, sb.toString());
     }
 
     private void update() {
         synchronized (mPids) {
-            Debug.MemoryInfo[] dinfos = mAm.getProcessMemoryInfo(mPidsArray);
-            for (int i = 0; i < dinfos.length; i++) {
-                Debug.MemoryInfo dinfo = dinfos[i];
-                if (i > mPids.size()) {
-                    if (DEBUG) Log.e(TAG, "update: unknown process info received: " + dinfo);
+            for (int i = 0; i < mPids.size(); i++) {
+                final int pid = mPids.get(i).intValue();
+                // rssValues contains [VmRSS, RssFile, RssAnon, VmSwap].
+                long[] rssValues = Process.getRss(pid);
+                if (rssValues == null && rssValues.length == 0) {
+                    if (DEBUG) Log.e(TAG, "update: Process.getRss() didn't provide any values.");
                     break;
                 }
-                final long pid = mPids.get(i).intValue();
+                long rss = rssValues[0];
                 final ProcessMemInfo info = mData.get(pid);
-                info.pss[info.head] = info.currentPss = dinfo.getTotalPss();
-                info.uss[info.head] = info.currentUss = dinfo.getTotalPrivateDirty();
-                info.head = (info.head + 1) % info.pss.length;
-                if (info.currentPss > info.max) info.max = info.currentPss;
-                if (info.currentUss > info.max) info.max = info.currentUss;
-                if (info.currentPss == 0) {
-                    if (DEBUG) Log.v(TAG, "update: pid " + pid + " has pss=0, it probably died");
+                info.rss[info.head] = info.currentRss = rss;
+                info.head = (info.head + 1) % info.rss.length;
+                if (info.currentRss > info.max) info.max = info.currentRss;
+                if (info.currentRss == 0) {
+                    if (DEBUG) Log.v(TAG, "update: pid " + pid + " has rss=0, it probably died");
                     mData.remove(pid);
                 }
             }
@@ -217,7 +213,7 @@
                 final long pid = mPids.get(i).intValue();
                 if (mData.get(pid) == null) {
                     mPids.remove(i);
-                    updatePidsArrayL();
+                    logPids();
                 }
             }
         }
@@ -270,7 +266,7 @@
 
 
     private static class MemoryIconDrawable extends Drawable {
-        long pss, limit;
+        long rss, limit;
         final Drawable baseIcon;
         final Paint paint = new Paint();
         final float dp;
@@ -281,9 +277,9 @@
             paint.setColor(QSTileImpl.getColorForState(context, STATE_ACTIVE));
         }
 
-        public void setPss(long pss) {
-            if (pss != this.pss) {
-                this.pss = pss;
+        public void setRss(long rss) {
+            if (rss != this.rss) {
+                this.rss = rss;
                 invalidateSelf();
             }
         }
@@ -299,8 +295,8 @@
         public void draw(Canvas canvas) {
             baseIcon.draw(canvas);
 
-            if (limit > 0 && pss > 0) {
-                float frac = Math.min(1f, (float) pss / limit);
+            if (limit > 0 && rss > 0) {
+                float frac = Math.min(1f, (float) rss / limit);
 
                 final Rect bounds = getBounds();
                 canvas.translate(bounds.left + 8 * dp, bounds.top + 5 * dp);
@@ -361,10 +357,10 @@
     }
 
     private static class MemoryGraphIcon extends QSTile.Icon {
-        long pss, limit;
+        long rss, limit;
 
-        public void setPss(long pss) {
-            this.pss = pss;
+        public void setRss(long rss) {
+            this.rss = rss;
         }
 
         public void setHeapLimit(long limit) {
@@ -374,7 +370,7 @@
         @Override
         public Drawable getDrawable(Context context) {
             final MemoryIconDrawable drawable = new MemoryIconDrawable(context);
-            drawable.setPss(pss);
+            drawable.setRss(rss);
             drawable.setLimit(limit);
             return drawable;
         }
@@ -464,14 +460,14 @@
                     ? "Dumping..."
                     : mContext.getString(R.string.heap_dump_tile_name);
             if (pmi != null) {
-                icon.setPss(pmi.currentPss);
+                icon.setRss(pmi.currentRss);
                 state.secondaryLabel =
                         String.format(
-                                "pss: %s / %s",
-                                formatBytes(pmi.currentPss * 1024),
+                                "rss: %s / %s",
+                                formatBytes(pmi.currentRss * 1024),
                                 formatBytes(gm.mHeapLimit * 1024));
             } else {
-                icon.setPss(0);
+                icon.setRss(0);
                 state.secondaryLabel = null;
             }
             state.icon = icon;
@@ -481,8 +477,8 @@
             refreshState();
         }
 
-        public long getPss() {
-            return pmi != null ? pmi.currentPss : 0;
+        public long getRss() {
+            return pmi != null ? pmi.currentRss : 0;
         }
 
         public long getHeapLimit() {
@@ -495,9 +491,8 @@
         public long pid;
         public String name;
         public long startTime;
-        public long currentPss, currentUss;
-        public long[] pss = new long[HEAP_TRACK_HISTORY_LEN];
-        public long[] uss = new long[HEAP_TRACK_HISTORY_LEN];
+        public long currentRss;
+        public long[] rss = new long[HEAP_TRACK_HISTORY_LEN];
         public long max = 1;
         public int head = 0;
 
@@ -519,28 +514,25 @@
             pw.print(name.replace('"', '-'));
             pw.print("\", \"start\": ");
             pw.print(startTime);
-            pw.print(", \"pss\": [");
-            // write pss values starting from the oldest, which is pss[head], wrapping around to
-            // pss[(head-1) % pss.length]
-            for (int i = 0; i < pss.length; i++) {
+            pw.print(", \"rss\": [");
+            // write rss values starting from the oldest, which is rss[head], wrapping around to
+            // rss[(head-1) % rss.length]
+            for (int i = 0; i < rss.length; i++) {
                 if (i > 0) pw.print(",");
-                pw.print(pss[(head + i) % pss.length]);
-            }
-            pw.print("], \"uss\": [");
-            for (int i = 0; i < uss.length; i++) {
-                if (i > 0) pw.print(",");
-                pw.print(uss[(head + i) % uss.length]);
+                pw.print(rss[(head + i) % rss.length]);
             }
             pw.println("] }");
         }
     }
 
     /** */
+    @Singleton
     public static class Service extends SystemUI implements Dumpable {
         private final GarbageMonitor mGarbageMonitor;
 
         @Inject
-        public Service(GarbageMonitor garbageMonitor) {
+        public Service(Context context, GarbageMonitor garbageMonitor) {
+            super(context);
             mGarbageMonitor = garbageMonitor;
         }
 
diff --git a/packages/SystemUI/src/com/android/systemui/util/sensors/AsyncSensorManager.java b/packages/SystemUI/src/com/android/systemui/util/sensors/AsyncSensorManager.java
index dcd0c58..2224c9c 100644
--- a/packages/SystemUI/src/com/android/systemui/util/sensors/AsyncSensorManager.java
+++ b/packages/SystemUI/src/com/android/systemui/util/sensors/AsyncSensorManager.java
@@ -139,6 +139,12 @@
 
     @Override
     protected boolean requestTriggerSensorImpl(TriggerEventListener listener, Sensor sensor) {
+        if (listener == null) {
+            throw new IllegalArgumentException("listener cannot be null");
+        }
+        if (sensor == null) {
+            throw new IllegalArgumentException("sensor cannot be null");
+        }
         mHandler.post(() -> {
             if (!mInner.requestTriggerSensor(listener, sensor)) {
                 Log.e(TAG, "Requesting " + listener + " for " + sensor + " failed.");
diff --git a/packages/SystemUI/src/com/android/systemui/volume/VolumeDialogComponent.java b/packages/SystemUI/src/com/android/systemui/volume/VolumeDialogComponent.java
index d2f185a..25a5139 100644
--- a/packages/SystemUI/src/com/android/systemui/volume/VolumeDialogComponent.java
+++ b/packages/SystemUI/src/com/android/systemui/volume/VolumeDialogComponent.java
@@ -27,7 +27,6 @@
 
 import com.android.settingslib.applications.InterestingConfigChanges;
 import com.android.systemui.Dependency;
-import com.android.systemui.SystemUI;
 import com.android.systemui.keyguard.KeyguardViewMediator;
 import com.android.systemui.plugins.ActivityStarter;
 import com.android.systemui.plugins.PluginDependencyProvider;
@@ -40,9 +39,13 @@
 import java.io.FileDescriptor;
 import java.io.PrintWriter;
 
+import javax.inject.Inject;
+import javax.inject.Singleton;
+
 /**
  * Implementation of VolumeComponent backed by the new volume dialog.
  */
+@Singleton
 public class VolumeDialogComponent implements VolumeComponent, TunerService.Tunable,
         VolumeDialogControllerImpl.UserActivityListener{
 
@@ -54,12 +57,12 @@
     public static final boolean DEFAULT_VOLUME_UP_TO_EXIT_SILENT = false;
     public static final boolean DEFAULT_DO_NOT_DISTURB_WHEN_SILENT = false;
 
-    private final SystemUI mSysui;
     protected final Context mContext;
     private final VolumeDialogControllerImpl mController;
     private final InterestingConfigChanges mConfigChanges = new InterestingConfigChanges(
             ActivityInfo.CONFIG_FONT_SCALE | ActivityInfo.CONFIG_LOCALE
             | ActivityInfo.CONFIG_ASSETS_PATHS | ActivityInfo.CONFIG_UI_MODE);
+    private final KeyguardViewMediator mKeyguardViewMediator;
     private VolumeDialog mDialog;
     private VolumePolicy mVolumePolicy = new VolumePolicy(
             DEFAULT_VOLUME_DOWN_TO_ENTER_SILENT,  // volumeDownToEnterSilent
@@ -68,9 +71,10 @@
             400    // vibrateToSilentDebounce
     );
 
-    public VolumeDialogComponent(SystemUI sysui, Context context) {
-        mSysui = sysui;
+    @Inject
+    public VolumeDialogComponent(Context context, KeyguardViewMediator keyguardViewMediator) {
         mContext = context;
+        mKeyguardViewMediator = keyguardViewMediator;
         mController = (VolumeDialogControllerImpl) Dependency.get(VolumeDialogController.class);
         mController.setUserActivityListener(this);
         // Allow plugins to reference the VolumeDialogController.
@@ -133,10 +137,7 @@
 
     @Override
     public void onUserActivity() {
-        final KeyguardViewMediator kvm = mSysui.getComponent(KeyguardViewMediator.class);
-        if (kvm != null) {
-            kvm.userActivity();
-        }
+        mKeyguardViewMediator.userActivity();
     }
 
     private void applyConfiguration() {
diff --git a/packages/SystemUI/src/com/android/systemui/volume/VolumeUI.java b/packages/SystemUI/src/com/android/systemui/volume/VolumeUI.java
index f8cf793..b7431397 100644
--- a/packages/SystemUI/src/com/android/systemui/volume/VolumeUI.java
+++ b/packages/SystemUI/src/com/android/systemui/volume/VolumeUI.java
@@ -16,18 +16,22 @@
 
 package com.android.systemui.volume;
 
+import android.content.Context;
 import android.content.res.Configuration;
 import android.os.Handler;
 import android.util.Log;
 
 import com.android.systemui.R;
 import com.android.systemui.SystemUI;
-import com.android.systemui.SystemUIFactory;
 import com.android.systemui.qs.tiles.DndTile;
 
 import java.io.FileDescriptor;
 import java.io.PrintWriter;
 
+import javax.inject.Inject;
+import javax.inject.Singleton;
+
+@Singleton
 public class VolumeUI extends SystemUI {
     private static final String TAG = "VolumeUI";
     private static boolean LOGD = Log.isLoggable(TAG, Log.DEBUG);
@@ -37,6 +41,12 @@
     private boolean mEnabled;
     private VolumeDialogComponent mVolumeComponent;
 
+    @Inject
+    public VolumeUI(Context context, VolumeDialogComponent volumeDialogComponent) {
+        super(context);
+        mVolumeComponent = volumeDialogComponent;
+    }
+
     @Override
     public void start() {
         boolean enableVolumeUi = mContext.getResources().getBoolean(R.bool.enable_volume_ui);
@@ -45,8 +55,6 @@
         mEnabled = enableVolumeUi || enableSafetyWarning;
         if (!mEnabled) return;
 
-        mVolumeComponent = SystemUIFactory.getInstance()
-                .createVolumeDialogComponent(this, mContext);
         mVolumeComponent.setEnableDialogs(enableVolumeUi, enableSafetyWarning);
         putComponent(VolumeComponent.class, getVolumeComponent());
         setDefaultVolumeController();
diff --git a/packages/SystemUI/tests/src/com/android/keyguard/CarrierTextControllerTest.java b/packages/SystemUI/tests/src/com/android/keyguard/CarrierTextControllerTest.java
index ede717b..1dd4863 100644
--- a/packages/SystemUI/tests/src/com/android/keyguard/CarrierTextControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/keyguard/CarrierTextControllerTest.java
@@ -26,20 +26,24 @@
 
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertNotEquals;
+import static org.junit.Assert.fail;
 import static org.mockito.ArgumentMatchers.any;
 import static org.mockito.ArgumentMatchers.anyBoolean;
 import static org.mockito.ArgumentMatchers.anyInt;
+import static org.mockito.Mockito.doAnswer;
 import static org.mockito.Mockito.mock;
 import static org.mockito.Mockito.never;
 import static org.mockito.Mockito.reset;
 import static org.mockito.Mockito.verify;
 import static org.mockito.Mockito.when;
 
-import android.content.Context;
 import android.net.ConnectivityManager;
 import android.net.wifi.WifiInfo;
 import android.net.wifi.WifiManager;
 import android.os.Handler;
+import android.os.HandlerThread;
+import android.os.Looper;
+import android.os.Process;
 import android.provider.Settings;
 import android.telephony.ServiceState;
 import android.telephony.SubscriptionInfo;
@@ -62,6 +66,7 @@
 import org.mockito.ArgumentCaptor;
 import org.mockito.Mock;
 import org.mockito.MockitoAnnotations;
+import org.mockito.invocation.InvocationOnMock;
 
 import java.util.ArrayList;
 import java.util.HashMap;
@@ -105,6 +110,14 @@
     private CarrierTextController mCarrierTextController;
     private TestableLooper mTestableLooper;
 
+    private Void checkMainThread(InvocationOnMock inv) {
+        Looper mainLooper = Dependency.get(Dependency.MAIN_HANDLER).getLooper();
+        if (!mainLooper.isCurrentThread()) {
+            fail("This call should be done from the main thread");
+        }
+        return null;
+    }
+
     @Before
     public void setUp() {
         MockitoAnnotations.initMocks(this);
@@ -112,6 +125,7 @@
 
         mContext.addMockSystemService(WifiManager.class, mWifiManager);
         mContext.addMockSystemService(ConnectivityManager.class, mConnectivityManager);
+        when(mConnectivityManager.isNetworkSupported(anyInt())).thenReturn(true);
         mContext.addMockSystemService(TelephonyManager.class, mTelephonyManager);
         mContext.addMockSystemService(SubscriptionManager.class, mSubscriptionManager);
         mContext.getOrCreateTestableResources().addOverride(
@@ -121,19 +135,43 @@
         mDependency.injectMockDependency(WakefulnessLifecycle.class);
         mDependency.injectTestDependency(Dependency.MAIN_HANDLER,
                 new Handler(mTestableLooper.getLooper()));
-        mDependency.injectMockDependency(KeyguardUpdateMonitor.class);
+        mDependency.injectTestDependency(KeyguardUpdateMonitor.class, mKeyguardUpdateMonitor);
+
+        doAnswer(this::checkMainThread).when(mKeyguardUpdateMonitor)
+                .registerCallback(any(KeyguardUpdateMonitorCallback.class));
+        doAnswer(this::checkMainThread).when(mKeyguardUpdateMonitor)
+                .removeCallback(any(KeyguardUpdateMonitorCallback.class));
 
         mCarrierTextCallbackInfo = new CarrierTextController.CarrierTextCallbackInfo("",
                 new CharSequence[]{}, false, new int[]{});
-        when(mTelephonyManager.getMaxPhoneCount()).thenReturn(3);
+        when(mTelephonyManager.getSupportedModemCount()).thenReturn(3);
 
-        mCarrierTextController = new TestCarrierTextController(mContext, SEPARATOR, true, true,
-                mKeyguardUpdateMonitor);
-        // This should not start listening on any of the real dependencies
+        mCarrierTextController = new CarrierTextController(mContext, SEPARATOR, true, true);
+        // This should not start listening on any of the real dependencies but will test that
+        // callbacks in mKeyguardUpdateMonitor are done in the mTestableLooper thread
         mCarrierTextController.setListening(mCarrierTextCallback);
     }
 
     @Test
+    public void testKeyguardUpdateMonitorCalledInMainThread() throws Exception {
+        // This test will run on the main looper (which is not the same as the looper set as MAIN
+        // for CarrierTextCallback. This will fail if calls to mKeyguardUpdateMonitor are not done
+        // through the looper set in the set up
+        HandlerThread thread = new HandlerThread("testThread",
+                Process.THREAD_PRIORITY_BACKGROUND);
+        thread.start();
+        TestableLooper testableLooper = new TestableLooper(thread.getLooper());
+        Handler h = new Handler(testableLooper.getLooper());
+        h.post(() -> {
+            mCarrierTextController.setListening(null);
+            mCarrierTextController.setListening(mCarrierTextCallback);
+        });
+        testableLooper.processAllMessages();
+        mTestableLooper.processAllMessages();
+        thread.quitSafely();
+    }
+
+    @Test
     public void testAirplaneMode() {
         Settings.Global.putInt(mContext.getContentResolver(), Settings.Global.AIRPLANE_MODE_ON, 1);
         reset(mCarrierTextCallback);
@@ -466,20 +504,4 @@
         assertEquals(TEST_CARRIER + SEPARATOR + TEST_CARRIER,
                 captor.getValue().carrierText);
     }
-
-    public static class TestCarrierTextController extends CarrierTextController {
-        private KeyguardUpdateMonitor mKUM;
-
-        public TestCarrierTextController(Context context, CharSequence separator,
-                boolean showAirplaneMode, boolean showMissingSim, KeyguardUpdateMonitor kum) {
-            super(context, separator, showAirplaneMode, showMissingSim);
-            mKUM = kum;
-        }
-
-        @Override
-        public void setListening(CarrierTextCallback callback) {
-            super.setListening(callback);
-            mKeyguardUpdateMonitor = mKUM;
-        }
-    }
 }
diff --git a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardUpdateMonitorTest.java b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardUpdateMonitorTest.java
index ad7bba1..57b0987 100644
--- a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardUpdateMonitorTest.java
+++ b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardUpdateMonitorTest.java
@@ -25,6 +25,7 @@
 import static org.mockito.ArgumentMatchers.anyBoolean;
 import static org.mockito.ArgumentMatchers.anyInt;
 import static org.mockito.ArgumentMatchers.anyString;
+import static org.mockito.ArgumentMatchers.eq;
 import static org.mockito.Mockito.clearInvocations;
 import static org.mockito.Mockito.doAnswer;
 import static org.mockito.Mockito.never;
@@ -481,6 +482,25 @@
         assertThat(mKeyguardUpdateMonitor.isUserUnlocked(randomUser)).isFalse();
     }
 
+    @Test
+    public void testTrustUsuallyManaged_whenTrustChanges() {
+        int user = KeyguardUpdateMonitor.getCurrentUser();
+        when(mTrustManager.isTrustUsuallyManaged(eq(user))).thenReturn(true);
+        mKeyguardUpdateMonitor.onTrustManagedChanged(false /* managed */, user);
+        assertThat(mKeyguardUpdateMonitor.isTrustUsuallyManaged(user)).isTrue();
+    }
+
+    @Test
+    public void testTrustUsuallyManaged_resetWhenUserIsRemoved() {
+        int user = KeyguardUpdateMonitor.getCurrentUser();
+        when(mTrustManager.isTrustUsuallyManaged(eq(user))).thenReturn(true);
+        mKeyguardUpdateMonitor.onTrustManagedChanged(false /* managed */, user);
+        assertThat(mKeyguardUpdateMonitor.isTrustUsuallyManaged(user)).isTrue();
+
+        mKeyguardUpdateMonitor.handleUserRemoved(user);
+        assertThat(mKeyguardUpdateMonitor.isTrustUsuallyManaged(user)).isFalse();
+    }
+
     private Intent putPhoneInfo(Intent intent, Bundle data, Boolean simInited) {
         int subscription = simInited
                 ? 1/* mock subid=1 */ : SubscriptionManager.DUMMY_SUBSCRIPTION_ID_BASE;
diff --git a/packages/SystemUI/tests/src/com/android/systemui/ExpandHelperTest.java b/packages/SystemUI/tests/src/com/android/systemui/ExpandHelperTest.java
index a07f25a..364ee66 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/ExpandHelperTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/ExpandHelperTest.java
@@ -30,6 +30,7 @@
 import androidx.test.filters.SmallTest;
 
 import com.android.keyguard.KeyguardUpdateMonitor;
+import com.android.systemui.statusbar.NotificationMediaManager;
 import com.android.systemui.statusbar.NotificationTestHelper;
 import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow;
 import com.android.systemui.util.Assert;
@@ -50,9 +51,10 @@
     @Before
     public void setUp() throws Exception {
         mDependency.injectMockDependency(KeyguardUpdateMonitor.class);
+        mDependency.injectMockDependency(NotificationMediaManager.class);
         Assert.sMainLooper = TestableLooper.get(this).getLooper();
         Context context = getContext();
-        mRow = new NotificationTestHelper(context).createRow();
+        mRow = new NotificationTestHelper(context, mDependency).createRow();
         mCallback = mock(ExpandHelper.Callback.class);
         mExpandHelper = new ExpandHelper(context, mCallback, 10, 100);
     }
diff --git a/packages/SystemUI/tests/src/com/android/systemui/ScreenDecorationsTest.java b/packages/SystemUI/tests/src/com/android/systemui/ScreenDecorationsTest.java
index 64ab060..c338d70 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/ScreenDecorationsTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/ScreenDecorationsTest.java
@@ -102,7 +102,7 @@
         when(mFragmentService.getFragmentHostManager(any())).thenReturn(mFragmentHostManager);
 
 
-        mScreenDecorations = new ScreenDecorations() {
+        mScreenDecorations = new ScreenDecorations(mContext) {
             @Override
             public void start() {
                 super.start();
@@ -126,7 +126,6 @@
                 mTestableLooper.processAllMessages();
             }
         };
-        mScreenDecorations.mContext = mContext;
         mScreenDecorations.mComponents = mContext.getComponents();
         reset(mTunerService);
     }
diff --git a/packages/SystemUI/tests/src/com/android/systemui/SizeCompatModeActivityControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/SizeCompatModeActivityControllerTest.java
index 3ea7150..06999bc 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/SizeCompatModeActivityControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/SizeCompatModeActivityControllerTest.java
@@ -58,13 +58,12 @@
         MockitoAnnotations.initMocks(this);
         doReturn(true).when(mMockButton).show();
 
-        mController = new SizeCompatModeActivityController(mMockAm) {
+        mController = new SizeCompatModeActivityController(mContext, mMockAm) {
             @Override
             RestartActivityButton createRestartButton(Context context) {
                 return mMockButton;
             };
         };
-        mController.mContext = mContext;
 
         ArgumentCaptor<TaskStackChangeListener> listenerCaptor =
                 ArgumentCaptor.forClass(TaskStackChangeListener.class);
diff --git a/packages/SystemUI/tests/src/com/android/systemui/SliceBroadcastRelayHandlerTest.java b/packages/SystemUI/tests/src/com/android/systemui/SliceBroadcastRelayHandlerTest.java
index 19e1a5c..a766885 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/SliceBroadcastRelayHandlerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/SliceBroadcastRelayHandlerTest.java
@@ -35,6 +35,7 @@
 
 import com.android.settingslib.SliceBroadcastRelay;
 
+import org.junit.Before;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import org.mockito.ArgumentCaptor;
@@ -44,6 +45,14 @@
 public class SliceBroadcastRelayHandlerTest extends SysuiTestCase {
 
     private static final String TEST_ACTION = "com.android.systemui.action.TEST_ACTION";
+    private SliceBroadcastRelayHandler mRelayHandler;
+    private Context mSpyContext;
+    @Before
+    public void setup() {
+        mSpyContext = spy(mContext);
+
+        mRelayHandler = new SliceBroadcastRelayHandler(mSpyContext);
+    }
 
     @Test
     public void testRegister() {
@@ -52,8 +61,6 @@
                 .authority("something")
                 .path("test")
                 .build();
-        SliceBroadcastRelayHandler relayHandler = new SliceBroadcastRelayHandler();
-        relayHandler.mContext = spy(mContext);
 
         Intent intent = new Intent(SliceBroadcastRelay.ACTION_REGISTER);
         intent.putExtra(SliceBroadcastRelay.EXTRA_URI, ContentProvider.maybeAddUserId(testUri, 0));
@@ -63,8 +70,8 @@
         intent.putExtra(SliceBroadcastRelay.EXTRA_FILTER, value);
         intent.putExtra(SliceBroadcastRelay.EXTRA_URI, testUri);
 
-        relayHandler.handleIntent(intent);
-        verify(relayHandler.mContext).registerReceiver(any(), eq(value));
+        mRelayHandler.handleIntent(intent);
+        verify(mSpyContext).registerReceiver(any(), eq(value));
     }
 
     @Test
@@ -74,8 +81,6 @@
                 .authority("something")
                 .path("test")
                 .build();
-        SliceBroadcastRelayHandler relayHandler = new SliceBroadcastRelayHandler();
-        relayHandler.mContext = spy(mContext);
 
         Intent intent = new Intent(SliceBroadcastRelay.ACTION_REGISTER);
         intent.putExtra(SliceBroadcastRelay.EXTRA_URI, ContentProvider.maybeAddUserId(testUri, 0));
@@ -84,14 +89,14 @@
         IntentFilter value = new IntentFilter(TEST_ACTION);
         intent.putExtra(SliceBroadcastRelay.EXTRA_FILTER, value);
 
-        relayHandler.handleIntent(intent);
+        mRelayHandler.handleIntent(intent);
         ArgumentCaptor<BroadcastReceiver> relay = ArgumentCaptor.forClass(BroadcastReceiver.class);
-        verify(relayHandler.mContext).registerReceiver(relay.capture(), eq(value));
+        verify(mSpyContext).registerReceiver(relay.capture(), eq(value));
 
         intent = new Intent(SliceBroadcastRelay.ACTION_UNREGISTER);
         intent.putExtra(SliceBroadcastRelay.EXTRA_URI, ContentProvider.maybeAddUserId(testUri, 0));
-        relayHandler.handleIntent(intent);
-        verify(relayHandler.mContext).unregisterReceiver(eq(relay.getValue()));
+        mRelayHandler.handleIntent(intent);
+        verify(mSpyContext).unregisterReceiver(eq(relay.getValue()));
     }
 
     @Test
@@ -101,12 +106,10 @@
                 .authority("something")
                 .path("test")
                 .build();
-        SliceBroadcastRelayHandler relayHandler = new SliceBroadcastRelayHandler();
-        relayHandler.mContext = spy(mContext);
 
         Intent intent = new Intent(SliceBroadcastRelay.ACTION_UNREGISTER);
         intent.putExtra(SliceBroadcastRelay.EXTRA_URI, ContentProvider.maybeAddUserId(testUri, 0));
-        relayHandler.handleIntent(intent);
+        mRelayHandler.handleIntent(intent);
         // No crash
     }
 
@@ -118,9 +121,6 @@
                 .authority("something")
                 .path("test")
                 .build();
-        SliceBroadcastRelayHandler relayHandler = new SliceBroadcastRelayHandler();
-        relayHandler.mContext = spy(mContext);
-
         Intent intent = new Intent(SliceBroadcastRelay.ACTION_REGISTER);
         intent.putExtra(SliceBroadcastRelay.EXTRA_URI, ContentProvider.maybeAddUserId(testUri, 0));
         intent.putExtra(SliceBroadcastRelay.EXTRA_RECEIVER,
@@ -128,10 +128,10 @@
         IntentFilter value = new IntentFilter(TEST_ACTION);
         intent.putExtra(SliceBroadcastRelay.EXTRA_FILTER, value);
 
-        relayHandler.handleIntent(intent);
+        mRelayHandler.handleIntent(intent);
         ArgumentCaptor<BroadcastReceiver> relay = ArgumentCaptor.forClass(BroadcastReceiver.class);
-        verify(relayHandler.mContext).registerReceiver(relay.capture(), eq(value));
-        relay.getValue().onReceive(relayHandler.mContext, new Intent(TEST_ACTION));
+        verify(mSpyContext).registerReceiver(relay.capture(), eq(value));
+        relay.getValue().onReceive(mSpyContext, new Intent(TEST_ACTION));
 
         verify(Receiver.sReceiver, timeout(2000)).onReceive(any(), any());
     }
diff --git a/packages/SystemUI/tests/src/com/android/systemui/SysuiBaseFragmentTest.java b/packages/SystemUI/tests/src/com/android/systemui/SysuiBaseFragmentTest.java
index a245d41..cf77850 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/SysuiBaseFragmentTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/SysuiBaseFragmentTest.java
@@ -24,6 +24,7 @@
 
 import androidx.test.InstrumentationRegistry;
 
+import com.android.systemui.assist.AssistManager;
 import com.android.systemui.utils.leaks.LeakCheckedTest;
 import com.android.systemui.utils.leaks.LeakCheckedTest.SysuiLeakCheck;
 
@@ -64,6 +65,7 @@
         when(inst.getTargetContext()).thenThrow(new RuntimeException(
                 "SysUI Tests should use SysuiTestCase#getContext or SysuiTestCase#mContext"));
         InstrumentationRegistry.registerInstance(inst, InstrumentationRegistry.getArguments());
+        mDependency.injectMockDependency(AssistManager.class);
     }
 
     @After
diff --git a/packages/SystemUI/tests/src/com/android/systemui/biometrics/AuthBiometricViewTest.java b/packages/SystemUI/tests/src/com/android/systemui/biometrics/AuthBiometricViewTest.java
index 7a09137..2c85424 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/biometrics/AuthBiometricViewTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/biometrics/AuthBiometricViewTest.java
@@ -24,6 +24,7 @@
 import static org.mockito.Mockito.verify;
 
 import android.content.Context;
+import android.hardware.biometrics.Authenticator;
 import android.hardware.biometrics.BiometricPrompt;
 import android.os.Bundle;
 import android.test.suitebuilder.annotation.SmallTest;
@@ -70,7 +71,7 @@
 
     @Test
     public void testOnAuthenticationSucceeded_noConfirmationRequired_sendsActionAuthenticated() {
-        initDialog(mContext, mCallback, new MockInjector());
+        initDialog(mContext, false /* allowDeviceCredential */, mCallback, new MockInjector());
 
         // The onAuthenticated runnable is posted when authentication succeeds.
         mBiometricView.onAuthenticationSucceeded();
@@ -81,7 +82,7 @@
 
     @Test
     public void testOnAuthenticationSucceeded_confirmationRequired_updatesDialogContents() {
-        initDialog(mContext, mCallback, new MockInjector());
+        initDialog(mContext, false /* allowDeviceCredential */, mCallback, new MockInjector());
 
         mBiometricView.setRequireConfirmation(true);
         mBiometricView.onAuthenticationSucceeded();
@@ -97,7 +98,7 @@
     @Test
     public void testPositiveButton_sendsActionAuthenticated() {
         Button button = new Button(mContext);
-        initDialog(mContext, mCallback, new MockInjector() {
+        initDialog(mContext, false /* allowDeviceCredential */, mCallback, new MockInjector() {
            @Override
             public Button getPositiveButton() {
                return button;
@@ -114,7 +115,7 @@
     @Test
     public void testNegativeButton_beforeAuthentication_sendsActionButtonNegative() {
         Button button = new Button(mContext);
-        initDialog(mContext, mCallback, new MockInjector() {
+        initDialog(mContext, false /* allowDeviceCredential */, mCallback, new MockInjector() {
             @Override
             public Button getNegativeButton() {
                 return button;
@@ -131,7 +132,7 @@
     @Test
     public void testNegativeButton_whenPendingConfirmation_sendsActionUserCanceled() {
         Button button = new Button(mContext);
-        initDialog(mContext, mCallback, new MockInjector() {
+        initDialog(mContext, false /* allowDeviceCredential */, mCallback, new MockInjector() {
             @Override
             public Button getNegativeButton() {
                 return button;
@@ -149,7 +150,7 @@
     @Test
     public void testTryAgainButton_sendsActionTryAgain() {
         Button button = new Button(mContext);
-        initDialog(mContext, mCallback, new MockInjector() {
+        initDialog(mContext, false /* allowDeviceCredential */, mCallback, new MockInjector() {
             @Override
             public Button getTryAgainButton() {
                 return button;
@@ -165,7 +166,7 @@
 
     @Test
     public void testError_sendsActionError() {
-        initDialog(mContext, mCallback, new MockInjector());
+        initDialog(mContext, false /* allowDeviceCredential */, mCallback, new MockInjector());
         final String testError = "testError";
         mBiometricView.onError(testError);
         waitForIdleSync();
@@ -176,7 +177,7 @@
 
     @Test
     public void testBackgroundClicked_sendsActionUserCanceled() {
-        initDialog(mContext, mCallback, new MockInjector());
+        initDialog(mContext, false /* allowDeviceCredential */, mCallback, new MockInjector());
 
         View view = new View(mContext);
         mBiometricView.setBackgroundView(view);
@@ -186,7 +187,7 @@
 
     @Test
     public void testBackgroundClicked_afterAuthenticated_neverSendsUserCanceled() {
-        initDialog(mContext, mCallback, new MockInjector());
+        initDialog(mContext, false /* allowDeviceCredential */, mCallback, new MockInjector());
 
         View view = new View(mContext);
         mBiometricView.setBackgroundView(view);
@@ -197,8 +198,7 @@
 
     @Test
     public void testBackgroundClicked_whenSmallDialog_neverSendsUserCanceled() {
-        initDialog(mContext, mCallback, new MockInjector());
-        mBiometricView.setPanelController(mPanelController);
+        initDialog(mContext, false /* allowDeviceCredential */, mCallback, new MockInjector());
         mBiometricView.updateSize(AuthDialog.SIZE_SMALL);
 
         View view = new View(mContext);
@@ -213,7 +213,7 @@
 
         Button tryAgainButton = new Button(mContext);
         TextView indicatorView = new TextView(mContext);
-        initDialog(mContext, mCallback, new MockInjector() {
+        initDialog(mContext, false /* allowDeviceCredential */, mCallback, new MockInjector() {
             @Override
             public Button getTryAgainButton() {
                 return tryAgainButton;
@@ -249,16 +249,18 @@
         // Create new dialog and restore the previous state into it
         Button tryAgainButton2 = new Button(mContext);
         TextView indicatorView2 = new TextView(mContext);
-        initDialog(mContext, mCallback, state, new MockInjector() {
-            @Override
-            public Button getTryAgainButton() {
-                return tryAgainButton2;
-            }
-            @Override
-            public TextView getIndicatorView() {
-                return indicatorView2;
-            }
-        });
+        initDialog(mContext, false /* allowDeviceCredential */, mCallback, state,
+                new MockInjector() {
+                    @Override
+                    public Button getTryAgainButton() {
+                        return tryAgainButton2;
+                    }
+
+                    @Override
+                    public TextView getIndicatorView() {
+                        return indicatorView2;
+                    }
+                });
         mBiometricView.setRequireConfirmation(requireConfirmation);
         waitForIdleSync();
 
@@ -271,26 +273,51 @@
         // dialog size is known.
     }
 
-    private Bundle buildBiometricPromptBundle() {
+    @Test
+    public void testNegativeButton_whenDeviceCredentialAllowed() throws InterruptedException {
+        Button negativeButton = new Button(mContext);
+        initDialog(mContext, true /* allowDeviceCredential */, mCallback, new MockInjector() {
+            @Override
+            public Button getNegativeButton() {
+                return negativeButton;
+            }
+        });
+
+        negativeButton.performClick();
+        waitForIdleSync();
+
+        verify(mCallback).onAction(AuthBiometricView.Callback.ACTION_USE_DEVICE_CREDENTIAL);
+    }
+
+    private Bundle buildBiometricPromptBundle(boolean allowDeviceCredential) {
         Bundle bundle = new Bundle();
         bundle.putCharSequence(BiometricPrompt.KEY_TITLE, "Title");
-        bundle.putCharSequence(BiometricPrompt.KEY_NEGATIVE_TEXT, "Negative");
+        int authenticators = Authenticator.TYPE_BIOMETRIC;
+        if (allowDeviceCredential) {
+            authenticators |= Authenticator.TYPE_CREDENTIAL;
+        } else {
+            bundle.putCharSequence(BiometricPrompt.KEY_NEGATIVE_TEXT, "Negative");
+        }
+        bundle.putInt(BiometricPrompt.KEY_AUTHENTICATORS_ALLOWED, authenticators);
         return bundle;
     }
 
-    private void initDialog(Context context, AuthBiometricView.Callback callback,
+    private void initDialog(Context context, boolean allowDeviceCredential,
+            AuthBiometricView.Callback callback,
             Bundle savedState, MockInjector injector) {
         mBiometricView = new TestableBiometricView(context, null, injector);
-        mBiometricView.setBiometricPromptBundle(buildBiometricPromptBundle());
+        mBiometricView.setBiometricPromptBundle(buildBiometricPromptBundle(allowDeviceCredential));
         mBiometricView.setCallback(callback);
         mBiometricView.restoreState(savedState);
         mBiometricView.onFinishInflateInternal();
         mBiometricView.onAttachedToWindowInternal();
+
+        mBiometricView.setPanelController(mPanelController);
     }
 
-    private void initDialog(Context context, AuthBiometricView.Callback callback,
-            MockInjector injector) {
-        initDialog(context, callback, null /* savedState */, injector);
+    private void initDialog(Context context, boolean allowDeviceCredential,
+            AuthBiometricView.Callback callback, MockInjector injector) {
+        initDialog(context, allowDeviceCredential, callback, null /* savedState */, injector);
     }
 
     private class MockInjector extends AuthBiometricView.Injector {
@@ -338,6 +365,16 @@
         public int getDelayAfterError() {
             return 0; // Keep this at 0 for tests to invoke callback immediately.
         }
+
+        @Override
+        public int getMediumToLargeAnimationDurationMs() {
+            return 0;
+        }
+
+        @Override
+        public int getAnimateCredentialStartDelayMs() {
+            return 0;
+        }
     }
 
     private class TestableBiometricView extends AuthBiometricView {
diff --git a/packages/SystemUI/tests/src/com/android/systemui/biometrics/AuthContainerViewTest.java b/packages/SystemUI/tests/src/com/android/systemui/biometrics/AuthContainerViewTest.java
index d4fc3f8..990f74a 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/biometrics/AuthContainerViewTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/biometrics/AuthContainerViewTest.java
@@ -16,12 +16,30 @@
 
 package com.android.systemui.biometrics;
 
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNull;
+import static org.mockito.ArgumentMatchers.any;
 import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.never;
 import static org.mockito.Mockito.verify;
 
+import android.content.Context;
+import android.hardware.biometrics.Authenticator;
+import android.hardware.biometrics.BiometricAuthenticator;
+import android.hardware.biometrics.BiometricPrompt;
+import android.os.Bundle;
 import android.test.suitebuilder.annotation.SmallTest;
 import android.testing.AndroidTestingRunner;
 import android.testing.TestableLooper.RunWithLooper;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.FrameLayout;
+import android.widget.ImageView;
+import android.widget.ScrollView;
 
 import com.android.systemui.SysuiTestCase;
 
@@ -43,22 +61,21 @@
     @Before
     public void setup() {
         MockitoAnnotations.initMocks(this);
-
-        AuthContainerView.Config config = new AuthContainerView.Config();
-        config.mContext = mContext;
-        config.mCallback = mCallback;
-        mAuthContainer = new TestableAuthContainer(config);
     }
 
     @Test
     public void testActionAuthenticated_sendsDismissedAuthenticated() {
+        initializeContainer(Authenticator.TYPE_BIOMETRIC);
+
         mAuthContainer.mBiometricCallback.onAction(
                 AuthBiometricView.Callback.ACTION_AUTHENTICATED);
-        verify(mCallback).onDismissed(eq(AuthDialogCallback.DISMISSED_AUTHENTICATED));
+        verify(mCallback).onDismissed(eq(AuthDialogCallback.DISMISSED_BIOMETRIC_AUTHENTICATED));
     }
 
     @Test
     public void testActionUserCanceled_sendsDismissedUserCanceled() {
+        initializeContainer(Authenticator.TYPE_BIOMETRIC);
+
         mAuthContainer.mBiometricCallback.onAction(
                 AuthBiometricView.Callback.ACTION_USER_CANCELED);
         verify(mCallback).onDismissed(eq(AuthDialogCallback.DISMISSED_USER_CANCELED));
@@ -66,6 +83,8 @@
 
     @Test
     public void testActionButtonNegative_sendsDismissedButtonNegative() {
+        initializeContainer(Authenticator.TYPE_BIOMETRIC);
+
         mAuthContainer.mBiometricCallback.onAction(
                 AuthBiometricView.Callback.ACTION_BUTTON_NEGATIVE);
         verify(mCallback).onDismissed(eq(AuthDialogCallback.DISMISSED_BUTTON_NEGATIVE));
@@ -73,6 +92,8 @@
 
     @Test
     public void testActionTryAgain_sendsTryAgain() {
+        initializeContainer(Authenticator.TYPE_BIOMETRIC);
+
         mAuthContainer.mBiometricCallback.onAction(
                 AuthBiometricView.Callback.ACTION_BUTTON_TRY_AGAIN);
         verify(mCallback).onTryAgainPressed();
@@ -80,14 +101,77 @@
 
     @Test
     public void testActionError_sendsDismissedError() {
+        initializeContainer(Authenticator.TYPE_BIOMETRIC);
+
         mAuthContainer.mBiometricCallback.onAction(
                 AuthBiometricView.Callback.ACTION_ERROR);
         verify(mCallback).onDismissed(AuthDialogCallback.DISMISSED_ERROR);
     }
 
+    @Test
+    public void testActionUseDeviceCredential_sendsOnDeviceCredentialPressed() {
+        initializeContainer(
+                Authenticator.TYPE_BIOMETRIC | Authenticator.TYPE_CREDENTIAL);
+
+        mAuthContainer.mBiometricCallback.onAction(
+                AuthBiometricView.Callback.ACTION_USE_DEVICE_CREDENTIAL);
+        verify(mCallback).onDeviceCredentialPressed();
+
+        // Credential view is attached to the frame layout
+        waitForIdleSync();
+        assertNotNull(mAuthContainer.mCredentialView);
+        verify(mAuthContainer.mFrameLayout).addView(eq(mAuthContainer.mCredentialView));
+    }
+
+    @Test
+    public void testAnimateToCredentialUI_invokesStartTransitionToCredentialUI() {
+        initializeContainer(
+                Authenticator.TYPE_BIOMETRIC | Authenticator.TYPE_CREDENTIAL);
+
+        mAuthContainer.mBiometricView = mock(AuthBiometricView.class);
+        mAuthContainer.animateToCredentialUI();
+        verify(mAuthContainer.mBiometricView).startTransitionToCredentialUI();
+    }
+
+    @Test
+    public void testShowBiometricUI() {
+        initializeContainer(Authenticator.TYPE_BIOMETRIC);
+
+        assertNotEquals(null, mAuthContainer.mBiometricView);
+
+        mAuthContainer.onAttachedToWindowInternal();
+        verify(mAuthContainer.mBiometricScrollView).addView(mAuthContainer.mBiometricView);
+        // Credential view is not added
+        verify(mAuthContainer.mFrameLayout, never()).addView(any());
+    }
+
+    @Test
+    public void testShowCredentialUI_doesNotInflateBiometricUI() {
+        initializeContainer(Authenticator.TYPE_CREDENTIAL);
+
+        mAuthContainer.onAttachedToWindowInternal();
+
+        assertNull(null, mAuthContainer.mBiometricView);
+        assertNotNull(mAuthContainer.mCredentialView);
+        verify(mAuthContainer.mFrameLayout).addView(mAuthContainer.mCredentialView);
+    }
+
+    private void initializeContainer(int authenticators) {
+        AuthContainerView.Config config = new AuthContainerView.Config();
+        config.mContext = mContext;
+        config.mCallback = mCallback;
+        config.mModalityMask |= BiometricAuthenticator.TYPE_FINGERPRINT;
+
+        Bundle bundle = new Bundle();
+        bundle.putInt(BiometricPrompt.KEY_AUTHENTICATORS_ALLOWED, authenticators);
+        config.mBiometricPromptBundle = bundle;
+
+        mAuthContainer = new TestableAuthContainer(config);
+    }
+
     private class TestableAuthContainer extends AuthContainerView {
         TestableAuthContainer(AuthContainerView.Config config) {
-            super(config);
+            super(config, new MockInjector());
         }
 
         @Override
@@ -95,4 +179,32 @@
             mConfig.mCallback.onDismissed(reason);
         }
     }
+
+    private final class MockInjector extends AuthContainerView.Injector {
+        @Override
+        public ScrollView getBiometricScrollView(FrameLayout parent) {
+            return mock(ScrollView.class);
+        }
+
+        @Override
+        public FrameLayout inflateContainerView(LayoutInflater factory, ViewGroup root) {
+            return mock(FrameLayout.class);
+        }
+
+        @Override
+        public AuthPanelController getPanelController(Context context, View view,
+                boolean isManagedProfile) {
+            return mock(AuthPanelController.class);
+        }
+
+        @Override
+        public ImageView getBackgroundView(FrameLayout parent) {
+            return mock(ImageView.class);
+        }
+
+        @Override
+        public View getPanelView(FrameLayout parent) {
+            return mock(View.class);
+        }
+    }
 }
diff --git a/packages/SystemUI/tests/src/com/android/systemui/biometrics/AuthControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/biometrics/AuthControllerTest.java
index eb7be4f..e1eb3b0 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/biometrics/AuthControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/biometrics/AuthControllerTest.java
@@ -22,8 +22,11 @@
 
 import static org.mockito.ArgumentMatchers.any;
 import static org.mockito.ArgumentMatchers.anyInt;
+import static org.mockito.ArgumentMatchers.anyString;
 import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.Mockito.doAnswer;
 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;
@@ -31,8 +34,11 @@
 import android.app.ActivityManager;
 import android.app.IActivityTaskManager;
 import android.content.ComponentName;
+import android.content.Context;
 import android.content.pm.PackageManager;
 import android.content.res.Configuration;
+import android.hardware.biometrics.Authenticator;
+import android.hardware.biometrics.BiometricConstants;
 import android.hardware.biometrics.BiometricPrompt;
 import android.hardware.biometrics.IBiometricServiceReceiverInternal;
 import android.os.Bundle;
@@ -69,7 +75,7 @@
     @Mock
     private AuthDialog mDialog2;
 
-    private TestableBiometricDialogImpl mBiometricDialogImpl;
+    private TestableAuthController mAuthController;
 
 
     @Before
@@ -90,78 +96,89 @@
         when(mDialog1.getOpPackageName()).thenReturn("Dialog1");
         when(mDialog2.getOpPackageName()).thenReturn("Dialog2");
 
-        mBiometricDialogImpl = new TestableBiometricDialogImpl(new MockInjector());
-        mBiometricDialogImpl.mContext = context;
-        mBiometricDialogImpl.mComponents = mContext.getComponents();
+        when(mDialog1.isAllowDeviceCredentials()).thenReturn(false);
+        when(mDialog2.isAllowDeviceCredentials()).thenReturn(false);
 
-        mBiometricDialogImpl.start();
+        mAuthController = new TestableAuthController(context, new MockInjector());
+        mAuthController.mComponents = mContext.getComponents();
+
+        mAuthController.start();
     }
 
     // Callback tests
 
     @Test
     public void testSendsReasonUserCanceled_whenDismissedByUserCancel() throws Exception {
-        showDialog(BiometricPrompt.TYPE_FACE);
-        mBiometricDialogImpl.onDismissed(AuthDialogCallback.DISMISSED_USER_CANCELED);
+        showDialog(Authenticator.TYPE_BIOMETRIC, BiometricPrompt.TYPE_FACE);
+        mAuthController.onDismissed(AuthDialogCallback.DISMISSED_USER_CANCELED);
         verify(mReceiver).onDialogDismissed(BiometricPrompt.DISMISSED_REASON_USER_CANCEL);
     }
 
     @Test
     public void testSendsReasonNegative_whenDismissedByButtonNegative() throws Exception {
-        showDialog(BiometricPrompt.TYPE_FACE);
-        mBiometricDialogImpl.onDismissed(AuthDialogCallback.DISMISSED_BUTTON_NEGATIVE);
+        showDialog(Authenticator.TYPE_BIOMETRIC, BiometricPrompt.TYPE_FACE);
+        mAuthController.onDismissed(AuthDialogCallback.DISMISSED_BUTTON_NEGATIVE);
         verify(mReceiver).onDialogDismissed(BiometricPrompt.DISMISSED_REASON_NEGATIVE);
     }
 
     @Test
     public void testSendsReasonConfirmed_whenDismissedByButtonPositive() throws Exception {
-        showDialog(BiometricPrompt.TYPE_FACE);
-        mBiometricDialogImpl.onDismissed(AuthDialogCallback.DISMISSED_BUTTON_POSITIVE);
-        verify(mReceiver).onDialogDismissed(BiometricPrompt.DISMISSED_REASON_CONFIRMED);
+        showDialog(Authenticator.TYPE_BIOMETRIC, BiometricPrompt.TYPE_FACE);
+        mAuthController.onDismissed(AuthDialogCallback.DISMISSED_BUTTON_POSITIVE);
+        verify(mReceiver).onDialogDismissed(BiometricPrompt.DISMISSED_REASON_BIOMETRIC_CONFIRMED);
     }
 
     @Test
     public void testSendsReasonConfirmNotRequired_whenDismissedByAuthenticated() throws Exception {
-        showDialog(BiometricPrompt.TYPE_FACE);
-        mBiometricDialogImpl.onDismissed(AuthDialogCallback.DISMISSED_AUTHENTICATED);
-        verify(mReceiver).onDialogDismissed(BiometricPrompt.DISMISSED_REASON_CONFIRM_NOT_REQUIRED);
+        showDialog(Authenticator.TYPE_BIOMETRIC, BiometricPrompt.TYPE_FACE);
+        mAuthController.onDismissed(AuthDialogCallback.DISMISSED_BIOMETRIC_AUTHENTICATED);
+        verify(mReceiver).onDialogDismissed(
+                BiometricPrompt.DISMISSED_REASON_BIOMETRIC_CONFIRM_NOT_REQUIRED);
     }
 
     @Test
     public void testSendsReasonError_whenDismissedByError() throws Exception {
-        showDialog(BiometricPrompt.TYPE_FACE);
-        mBiometricDialogImpl.onDismissed(AuthDialogCallback.DISMISSED_ERROR);
+        showDialog(Authenticator.TYPE_BIOMETRIC, BiometricPrompt.TYPE_FACE);
+        mAuthController.onDismissed(AuthDialogCallback.DISMISSED_ERROR);
         verify(mReceiver).onDialogDismissed(BiometricPrompt.DISMISSED_REASON_ERROR);
     }
 
     @Test
-    public void testSendsReasonDismissedBySystemServer_whenDismissedByServer() throws Exception {
-        showDialog(BiometricPrompt.TYPE_FACE);
-        mBiometricDialogImpl.onDismissed(AuthDialogCallback.DISMISSED_BY_SYSTEM_SERVER);
+    public void testSendsReasonServerRequested_whenDismissedByServer() throws Exception {
+        showDialog(Authenticator.TYPE_BIOMETRIC, BiometricPrompt.TYPE_FACE);
+        mAuthController.onDismissed(AuthDialogCallback.DISMISSED_BY_SYSTEM_SERVER);
         verify(mReceiver).onDialogDismissed(BiometricPrompt.DISMISSED_REASON_SERVER_REQUESTED);
     }
 
+    @Test
+    public void testSendsReasonCredentialConfirmed_whenDeviceCredentialAuthenticated()
+            throws Exception {
+        showDialog(Authenticator.TYPE_BIOMETRIC, BiometricPrompt.TYPE_FACE);
+        mAuthController.onDismissed(AuthDialogCallback.DISMISSED_CREDENTIAL_AUTHENTICATED);
+        verify(mReceiver).onDialogDismissed(BiometricPrompt.DISMISSED_REASON_CREDENTIAL_CONFIRMED);
+    }
+
     // Statusbar tests
 
     @Test
     public void testShowInvoked_whenSystemRequested()
             throws Exception {
-        showDialog(BiometricPrompt.TYPE_FACE);
+        showDialog(Authenticator.TYPE_BIOMETRIC, BiometricPrompt.TYPE_FACE);
         verify(mDialog1).show(any(), any());
     }
 
     @Test
-    public void testOnAuthenticationSucceededInvoked_whenSystemRequested() throws Exception {
-        showDialog(BiometricPrompt.TYPE_FACE);
-        mBiometricDialogImpl.onBiometricAuthenticated(true, null /* failureReason */);
+    public void testOnAuthenticationSucceededInvoked_whenSystemRequested() {
+        showDialog(Authenticator.TYPE_BIOMETRIC, BiometricPrompt.TYPE_FACE);
+        mAuthController.onBiometricAuthenticated(true, null /* failureReason */);
         verify(mDialog1).onAuthenticationSucceeded();
     }
 
     @Test
-    public void testOnAuthenticationFailedInvoked_whenSystemRequested() throws Exception {
-        showDialog(BiometricPrompt.TYPE_FACE);
+    public void testOnAuthenticationFailedInvoked_whenSystemRequested() {
+        showDialog(Authenticator.TYPE_BIOMETRIC, BiometricPrompt.TYPE_FACE);
         final String failureReason = "failure reason";
-        mBiometricDialogImpl.onBiometricAuthenticated(false, failureReason);
+        mAuthController.onBiometricAuthenticated(false, failureReason);
 
         ArgumentCaptor<String> captor = ArgumentCaptor.forClass(String.class);
         verify(mDialog1).onAuthenticationFailed(captor.capture());
@@ -170,10 +187,10 @@
     }
 
     @Test
-    public void testOnHelpInvoked_whenSystemRequested() throws Exception {
-        showDialog(BiometricPrompt.TYPE_FACE);
+    public void testOnHelpInvoked_whenSystemRequested() {
+        showDialog(Authenticator.TYPE_BIOMETRIC, BiometricPrompt.TYPE_FACE);
         final String helpMessage = "help";
-        mBiometricDialogImpl.onBiometricHelp(helpMessage);
+        mAuthController.onBiometricHelp(helpMessage);
 
         ArgumentCaptor<String> captor = ArgumentCaptor.forClass(String.class);
         verify(mDialog1).onHelp(captor.capture());
@@ -182,10 +199,11 @@
     }
 
     @Test
-    public void testOnErrorInvoked_whenSystemRequested() throws Exception {
-        showDialog(BiometricPrompt.TYPE_FACE);
+    public void testOnErrorInvoked_whenSystemRequested() {
+        showDialog(Authenticator.TYPE_BIOMETRIC, BiometricPrompt.TYPE_FACE);
+        final int error = 1;
         final String errMessage = "error message";
-        mBiometricDialogImpl.onBiometricError(errMessage);
+        mAuthController.onBiometricError(error, errMessage);
 
         ArgumentCaptor<String> captor = ArgumentCaptor.forClass(String.class);
         verify(mDialog1).onError(captor.capture());
@@ -194,30 +212,82 @@
     }
 
     @Test
-    public void testDismissWithoutCallbackInvoked_whenSystemRequested() throws Exception {
-        showDialog(BiometricPrompt.TYPE_FACE);
-        mBiometricDialogImpl.hideBiometricDialog();
+    public void testErrorLockout_whenCredentialAllowed_AnimatesToCredentialUI() {
+        showDialog(Authenticator.TYPE_BIOMETRIC, BiometricPrompt.TYPE_FACE);
+        final int error = BiometricConstants.BIOMETRIC_ERROR_LOCKOUT;
+        final String errorString = "lockout";
+
+        when(mDialog1.isAllowDeviceCredentials()).thenReturn(true);
+
+        mAuthController.onBiometricError(error, errorString);
+        verify(mDialog1, never()).onError(anyString());
+        verify(mDialog1).animateToCredentialUI();
+    }
+
+    @Test
+    public void testErrorLockoutPermanent_whenCredentialAllowed_AnimatesToCredentialUI() {
+        showDialog(Authenticator.TYPE_BIOMETRIC, BiometricPrompt.TYPE_FACE);
+        final int error = BiometricConstants.BIOMETRIC_ERROR_LOCKOUT_PERMANENT;
+        final String errorString = "lockout_permanent";
+
+        when(mDialog1.isAllowDeviceCredentials()).thenReturn(true);
+
+        mAuthController.onBiometricError(error, errorString);
+        verify(mDialog1, never()).onError(anyString());
+        verify(mDialog1).animateToCredentialUI();
+    }
+
+    @Test
+    public void testErrorLockout_whenCredentialNotAllowed_sendsOnError() {
+        showDialog(Authenticator.TYPE_BIOMETRIC, BiometricPrompt.TYPE_FACE);
+        final int error = BiometricConstants.BIOMETRIC_ERROR_LOCKOUT;
+        final String errorString = "lockout";
+
+        when(mDialog1.isAllowDeviceCredentials()).thenReturn(false);
+
+        mAuthController.onBiometricError(error, errorString);
+        verify(mDialog1).onError(eq(errorString));
+        verify(mDialog1, never()).animateToCredentialUI();
+    }
+
+    @Test
+    public void testErrorLockoutPermanent_whenCredentialNotAllowed_sendsOnError() {
+        showDialog(Authenticator.TYPE_BIOMETRIC, BiometricPrompt.TYPE_FACE);
+        final int error = BiometricConstants.BIOMETRIC_ERROR_LOCKOUT_PERMANENT;
+        final String errorString = "lockout_permanent";
+
+        when(mDialog1.isAllowDeviceCredentials()).thenReturn(false);
+
+        mAuthController.onBiometricError(error, errorString);
+        verify(mDialog1).onError(eq(errorString));
+        verify(mDialog1, never()).animateToCredentialUI();
+    }
+
+    @Test
+    public void testDismissWithoutCallbackInvoked_whenSystemRequested() {
+        showDialog(Authenticator.TYPE_BIOMETRIC, BiometricPrompt.TYPE_FACE);
+        mAuthController.hideAuthenticationDialog();
         verify(mDialog1).dismissFromSystemServer();
     }
 
     @Test
-    public void testClientNotified_whenDismissedBySystemServer() throws Exception {
-        showDialog(BiometricPrompt.TYPE_FACE);
-        mBiometricDialogImpl.hideBiometricDialog();
+    public void testClientNotified_whenDismissedBySystemServer() {
+        showDialog(Authenticator.TYPE_BIOMETRIC, BiometricPrompt.TYPE_FACE);
+        mAuthController.hideAuthenticationDialog();
         verify(mDialog1).dismissFromSystemServer();
 
-        assertNotNull(mBiometricDialogImpl.mCurrentDialog);
-        assertNotNull(mBiometricDialogImpl.mReceiver);
+        assertNotNull(mAuthController.mCurrentDialog);
+        assertNotNull(mAuthController.mReceiver);
     }
 
     // Corner case tests
 
     @Test
-    public void testShowNewDialog_beforeOldDialogDismissed_SkipsAnimations() throws Exception {
-        showDialog(BiometricPrompt.TYPE_FACE);
+    public void testShowNewDialog_beforeOldDialogDismissed_SkipsAnimations() {
+        showDialog(Authenticator.TYPE_BIOMETRIC, BiometricPrompt.TYPE_FACE);
         verify(mDialog1).show(any(), any());
 
-        showDialog(BiometricPrompt.TYPE_FACE);
+        showDialog(Authenticator.TYPE_BIOMETRIC, BiometricPrompt.TYPE_FACE);
 
         // First dialog should be dismissed without animation
         verify(mDialog1).dismissWithoutCallback(eq(false) /* animate */);
@@ -227,11 +297,20 @@
     }
 
     @Test
-    public void testConfigurationPersists_whenOnConfigurationChanged() throws Exception {
-        showDialog(BiometricPrompt.TYPE_FACE);
+    public void testConfigurationPersists_whenOnConfigurationChanged() {
+        showDialog(Authenticator.TYPE_BIOMETRIC, BiometricPrompt.TYPE_FACE);
         verify(mDialog1).show(any(), any());
 
-        mBiometricDialogImpl.onConfigurationChanged(new Configuration());
+        // Return that the UI is in "showing" state
+        doAnswer(invocation -> {
+            Object[] args = invocation.getArguments();
+            Bundle savedState = (Bundle) args[0];
+            savedState.putInt(
+                    AuthDialog.KEY_CONTAINER_STATE, AuthContainerView.STATE_SHOWING);
+            return null; // onSaveState returns void
+        }).when(mDialog1).onSaveState(any());
+
+        mAuthController.onConfigurationChanged(new Configuration());
 
         ArgumentCaptor<Bundle> captor = ArgumentCaptor.forClass(Bundle.class);
         verify(mDialog1).onSaveState(captor.capture());
@@ -248,37 +327,63 @@
     }
 
     @Test
+    public void testConfigurationPersists_whenBiometricFallbackToCredential() {
+        showDialog(Authenticator.TYPE_CREDENTIAL | Authenticator.TYPE_BIOMETRIC,
+                BiometricPrompt.TYPE_FACE);
+        verify(mDialog1).show(any(), any());
+
+        // Pretend that the UI is now showing device credential UI.
+        doAnswer(invocation -> {
+            Object[] args = invocation.getArguments();
+            Bundle savedState = (Bundle) args[0];
+            savedState.putInt(
+                    AuthDialog.KEY_CONTAINER_STATE, AuthContainerView.STATE_SHOWING);
+            savedState.putBoolean(AuthDialog.KEY_CREDENTIAL_SHOWING, true);
+            return null; // onSaveState returns void
+        }).when(mDialog1).onSaveState(any());
+
+        mAuthController.onConfigurationChanged(new Configuration());
+
+        // Check that the new dialog was initialized to the credential UI.
+        ArgumentCaptor<Bundle> captor = ArgumentCaptor.forClass(Bundle.class);
+        verify(mDialog2).show(any(), captor.capture());
+        assertEquals(Authenticator.TYPE_CREDENTIAL,
+                mAuthController.mLastBiometricPromptBundle
+                        .getInt(BiometricPrompt.KEY_AUTHENTICATORS_ALLOWED));
+    }
+
+    @Test
     public void testClientNotified_whenTaskStackChangesDuringAuthentication() throws Exception {
-        showDialog(BiometricPrompt.TYPE_FACE);
+        showDialog(Authenticator.TYPE_BIOMETRIC, BiometricPrompt.TYPE_FACE);
 
         List<ActivityManager.RunningTaskInfo> tasks = new ArrayList<>();
         ActivityManager.RunningTaskInfo taskInfo = mock(ActivityManager.RunningTaskInfo.class);
         taskInfo.topActivity = mock(ComponentName.class);
         when(taskInfo.topActivity.getPackageName()).thenReturn("other_package");
         tasks.add(taskInfo);
-        when(mBiometricDialogImpl.mActivityTaskManager.getTasks(anyInt())).thenReturn(tasks);
+        when(mAuthController.mActivityTaskManager.getTasks(anyInt())).thenReturn(tasks);
 
-        mBiometricDialogImpl.mTaskStackListener.onTaskStackChanged();
+        mAuthController.mTaskStackListener.onTaskStackChanged();
         waitForIdleSync();
 
-        assertNull(mBiometricDialogImpl.mCurrentDialog);
-        assertNull(mBiometricDialogImpl.mReceiver);
+        assertNull(mAuthController.mCurrentDialog);
+        assertNull(mAuthController.mReceiver);
         verify(mDialog1).dismissWithoutCallback(true /* animate */);
         verify(mReceiver).onDialogDismissed(eq(BiometricPrompt.DISMISSED_REASON_USER_CANCEL));
     }
 
     // Helpers
 
-    private void showDialog(int type) {
-        mBiometricDialogImpl.showBiometricDialog(createTestDialogBundle(),
+    private void showDialog(int authenticators, int biometricModality) {
+        mAuthController.showAuthenticationDialog(createTestDialogBundle(authenticators),
                 mReceiver /* receiver */,
-                type,
+                biometricModality,
                 true /* requireConfirmation */,
                 0 /* userId */,
                 "testPackage");
     }
 
-    private Bundle createTestDialogBundle() {
+    private Bundle createTestDialogBundle(int authenticators) {
         Bundle bundle = new Bundle();
 
         bundle.putCharSequence(BiometricPrompt.KEY_TITLE, "Title");
@@ -290,20 +395,26 @@
         // by user settings, and should be tested in BiometricService.
         bundle.putBoolean(BiometricPrompt.KEY_REQUIRE_CONFIRMATION, true);
 
+        bundle.putInt(BiometricPrompt.KEY_AUTHENTICATORS_ALLOWED, authenticators);
+
         return bundle;
     }
 
-    private final class TestableBiometricDialogImpl extends AuthController {
+    private final class TestableAuthController extends AuthController {
         private int mBuildCount = 0;
+        private Bundle mLastBiometricPromptBundle;
 
-        public TestableBiometricDialogImpl(Injector injector) {
-            super(injector);
+        TestableAuthController(Context context, Injector injector) {
+            super(context, injector);
         }
 
         @Override
         protected AuthDialog buildDialog(Bundle biometricPromptBundle,
                 boolean requireConfirmation, int userId, int type, String opPackageName,
                 boolean skipIntro) {
+
+            mLastBiometricPromptBundle = biometricPromptBundle;
+
             AuthDialog dialog;
             if (mBuildCount == 0) {
                 dialog = mDialog1;
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 2798c6b..dd5211d 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/bubbles/BubbleControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/bubbles/BubbleControllerTest.java
@@ -33,6 +33,7 @@
 import static org.mockito.ArgumentMatchers.any;
 import static org.mockito.ArgumentMatchers.anyBoolean;
 import static org.mockito.ArgumentMatchers.anyInt;
+import static org.mockito.ArgumentMatchers.anyString;
 import static org.mockito.Mockito.atLeastOnce;
 import static org.mockito.Mockito.mock;
 import static org.mockito.Mockito.never;
@@ -91,7 +92,6 @@
 @RunWith(AndroidTestingRunner.class)
 @TestableLooper.RunWithLooper(setAsMainLooper = true)
 public class BubbleControllerTest extends SysuiTestCase {
-
     @Mock
     private NotificationEntryManager mNotificationEntryManager;
     @Mock
@@ -158,7 +158,7 @@
         mStatusBarWindowController.add(mStatusBarView, 120 /* height */);
 
         // Need notifications for bubbles
-        mNotificationTestHelper = new NotificationTestHelper(mContext);
+        mNotificationTestHelper = new NotificationTestHelper(mContext, mDependency);
         mRow = mNotificationTestHelper.createBubble(mDeleteIntent);
         mRow2 = mNotificationTestHelper.createBubble(mDeleteIntent);
         mNonBubbleNotifRow = mNotificationTestHelper.createRow();
@@ -223,13 +223,13 @@
         mBubbleController.updateBubble(mRow.getEntry());
         assertNotNull(mBubbleData.getBubbleWithKey(mRow.getEntry().key));
         assertTrue(mBubbleController.hasBubbles());
-        verify(mNotificationEntryManager).updateNotifications();
+        verify(mNotificationEntryManager).updateNotifications(any());
         verify(mBubbleStateChangeListener).onHasBubblesChanged(true);
 
         mBubbleController.removeBubble(mRow.getEntry().key, BubbleController.DISMISS_USER_GESTURE);
         assertFalse(mStatusBarWindowController.getBubblesShowing());
         assertNull(mBubbleData.getBubbleWithKey(mRow.getEntry().key));
-        verify(mNotificationEntryManager, times(2)).updateNotifications();
+        verify(mNotificationEntryManager, times(2)).updateNotifications(anyString());
         verify(mBubbleStateChangeListener).onHasBubblesChanged(false);
     }
 
@@ -257,16 +257,16 @@
     @Test
     public void testDismissStack() {
         mBubbleController.updateBubble(mRow.getEntry());
-        verify(mNotificationEntryManager, times(1)).updateNotifications();
+        verify(mNotificationEntryManager, times(1)).updateNotifications(any());
         assertNotNull(mBubbleData.getBubbleWithKey(mRow.getEntry().key));
         mBubbleController.updateBubble(mRow2.getEntry());
-        verify(mNotificationEntryManager, times(2)).updateNotifications();
+        verify(mNotificationEntryManager, times(2)).updateNotifications(any());
         assertNotNull(mBubbleData.getBubbleWithKey(mRow2.getEntry().key));
         assertTrue(mBubbleController.hasBubbles());
 
         mBubbleController.dismissStack(BubbleController.DISMISS_USER_GESTURE);
         assertFalse(mStatusBarWindowController.getBubblesShowing());
-        verify(mNotificationEntryManager, times(3)).updateNotifications();
+        verify(mNotificationEntryManager, times(3)).updateNotifications(any());
         assertNull(mBubbleData.getBubbleWithKey(mRow.getEntry().key));
         assertNull(mBubbleData.getBubbleWithKey(mRow2.getEntry().key));
     }
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 392a7cb..96ee079 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/bubbles/BubbleDataTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/bubbles/BubbleDataTest.java
@@ -99,7 +99,7 @@
 
     @Before
     public void setUp() throws Exception {
-        mNotificationTestHelper = new NotificationTestHelper(mContext);
+        mNotificationTestHelper = new NotificationTestHelper(mContext, mDependency);
         MockitoAnnotations.initMocks(this);
 
         mEntryA1 = createBubbleEntry(1, "a1", "package.a");
diff --git a/packages/SystemUI/tests/src/com/android/systemui/power/PowerUITest.java b/packages/SystemUI/tests/src/com/android/systemui/power/PowerUITest.java
index 4958c64..8f4de3f 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/power/PowerUITest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/power/PowerUITest.java
@@ -682,8 +682,7 @@
     }
 
     private void createPowerUi() {
-        mPowerUI = new PowerUI(mBroadcastDispatcher);
-        mPowerUI.mContext = mContext;
+        mPowerUI = new PowerUI(mContext, mBroadcastDispatcher);
         mPowerUI.mComponents = mContext.getComponents();
         mPowerUI.mThermalService = mThermalServiceMock;
     }
diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/QSTileHostTest.java b/packages/SystemUI/tests/src/com/android/systemui/qs/QSTileHostTest.java
index 07fbbcf..7752014 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/qs/QSTileHostTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/qs/QSTileHostTest.java
@@ -60,6 +60,7 @@
 import java.io.PrintWriter;
 import java.io.StringWriter;
 import java.util.List;
+import java.util.Objects;
 
 import javax.inject.Provider;
 
@@ -190,8 +191,7 @@
             // changed
             String newSetting = Settings.Secure.getStringForUser(getContext().getContentResolver(),
                     TILES_SETTING, ActivityManager.getCurrentUser());
-            // newSetting is not null, as it has just been set.
-            if (!newSetting.equals(previousSetting)) {
+            if (!Objects.equals(newSetting, previousSetting)) {
                 onTuningChanged(TILES_SETTING, newSetting);
             }
         }
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/CommandQueueTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/CommandQueueTest.java
index b252a0d..1bd01e1 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/CommandQueueTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/CommandQueueTest.java
@@ -367,12 +367,13 @@
     }
 
     @Test
-    public void testShowBiometricDialog() {
+    public void testShowAuthenticationDialog() {
         Bundle bundle = new Bundle();
         String packageName = "test";
-        mCommandQueue.showBiometricDialog(bundle, null /* receiver */, 1, true, 3, packageName);
+        mCommandQueue.showAuthenticationDialog(bundle, null /* receiver */, 1, true, 3,
+                packageName);
         waitForIdleSync();
-        verify(mCallbacks).showBiometricDialog(eq(bundle), eq(null), eq(1), eq(true), eq(3),
+        verify(mCallbacks).showAuthenticationDialog(eq(bundle), eq(null), eq(1), eq(true), eq(3),
                 eq(packageName));
     }
 
@@ -394,16 +395,17 @@
 
     @Test
     public void testOnBiometricError() {
+        final int errorCode = 1;
         String errorMessage = "test_error_message";
-        mCommandQueue.onBiometricError(errorMessage);
+        mCommandQueue.onBiometricError(errorCode, errorMessage);
         waitForIdleSync();
-        verify(mCallbacks).onBiometricError(eq(errorMessage));
+        verify(mCallbacks).onBiometricError(eq(errorCode), eq(errorMessage));
     }
 
     @Test
-    public void testHideBiometricDialog() {
-        mCommandQueue.hideBiometricDialog();
+    public void testHideAuthenticationDialog() {
+        mCommandQueue.hideAuthenticationDialog();
         waitForIdleSync();
-        verify(mCallbacks).hideBiometricDialog();
+        verify(mCallbacks).hideAuthenticationDialog();
     }
 }
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/NavigationBarControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/NavigationBarControllerTest.java
index 618272c..cfa4065a 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/NavigationBarControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/NavigationBarControllerTest.java
@@ -23,6 +23,7 @@
 import static org.mockito.ArgumentMatchers.anyBoolean;
 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.doNothing;
 import static org.mockito.Mockito.doReturn;
@@ -31,15 +32,10 @@
 import static org.mockito.Mockito.reset;
 import static org.mockito.Mockito.spy;
 import static org.mockito.Mockito.verify;
-import static org.mockito.Mockito.when;
 
-import android.content.Context;
-import android.hardware.display.DisplayManager;
 import android.testing.AndroidTestingRunner;
 import android.testing.TestableLooper.RunWithLooper;
 import android.util.SparseArray;
-import android.view.Display;
-import android.view.WindowManager;
 
 import androidx.test.filters.SmallTest;
 
@@ -59,7 +55,6 @@
 public class NavigationBarControllerTest extends SysuiTestCase {
 
     private NavigationBarController mNavigationBarController;
-    private Display mDisplay;
     private NavigationBarFragment mDefaultNavBar;
     private NavigationBarFragment mSecondaryNavBar;
 
@@ -89,37 +84,28 @@
     @After
     public void tearDown() {
         mNavigationBarController = null;
-        mDisplay = null;
         mDefaultNavBar = null;
         mSecondaryNavBar = null;
     }
 
     @Test
     public void testCreateNavigationBarsIncludeDefaultTrue() {
-        initializeDisplayManager();
         doNothing().when(mNavigationBarController).createNavigationBar(any(), any());
 
         mNavigationBarController.createNavigationBars(true, null);
 
-        verify(mNavigationBarController).createNavigationBar(any(Display.class), any());
+        verify(mNavigationBarController).createNavigationBar(
+                argThat(display -> display.getDisplayId() == DEFAULT_DISPLAY), any());
     }
 
     @Test
     public void testCreateNavigationBarsIncludeDefaultFalse() {
-        initializeDisplayManager();
         doNothing().when(mNavigationBarController).createNavigationBar(any(), any());
 
         mNavigationBarController.createNavigationBars(false, null);
 
-        verify(mNavigationBarController, never()).createNavigationBar(any(), any());
-    }
-
-    private void initializeDisplayManager() {
-        DisplayManager displayManager = mock(DisplayManager.class);
-        mDisplay = mContext.getSystemService(WindowManager.class).getDefaultDisplay();
-        Display[] displays = {mDisplay};
-        when(displayManager.getDisplays()).thenReturn(displays);
-        mContext.addMockSystemService(Context.DISPLAY_SERVICE, displayManager);
+        verify(mNavigationBarController, never()).createNavigationBar(
+                argThat(display -> display.getDisplayId() == DEFAULT_DISPLAY), any());
     }
 
     // Tests if NPE occurs when call checkNavBarModes() with invalid display.
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/NonPhoneDependencyTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/NonPhoneDependencyTest.java
index a0a410d..e67aa69 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/NonPhoneDependencyTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/NonPhoneDependencyTest.java
@@ -52,7 +52,7 @@
  */
 @SmallTest
 @RunWith(AndroidTestingRunner.class)
-@TestableLooper.RunWithLooper
+@TestableLooper.RunWithLooper(setAsMainLooper = true)
 public class NonPhoneDependencyTest extends SysuiTestCase {
     @Mock private NotificationPresenter mPresenter;
     @Mock private NotificationListContainer mListContainer;
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationLockscreenUserManagerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationLockscreenUserManagerTest.java
index a027643..85a0fbd 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationLockscreenUserManagerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationLockscreenUserManagerTest.java
@@ -25,6 +25,7 @@
 import static junit.framework.Assert.assertTrue;
 
 import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.anyString;
 import static org.mockito.Mockito.times;
 import static org.mockito.Mockito.verify;
 import static org.mockito.Mockito.when;
@@ -51,6 +52,7 @@
 import com.android.systemui.statusbar.notification.collection.NotificationEntry;
 import com.android.systemui.statusbar.phone.StatusBarKeyguardViewManager;
 import com.android.systemui.statusbar.policy.DeviceProvisionedController;
+import com.android.systemui.statusbar.policy.KeyguardStateController;
 
 import com.google.android.collect.Lists;
 
@@ -82,6 +84,7 @@
         mDependency.injectTestDependency(NotificationEntryManager.class, mEntryManager);
         mDependency.injectTestDependency(DeviceProvisionedController.class,
                 mDeviceProvisionedController);
+        mDependency.injectMockDependency(KeyguardStateController.class);
 
         mContext.addMockSystemService(UserManager.class, mUserManager);
         mCurrentUserId = ActivityManager.getCurrentUser();
@@ -99,7 +102,7 @@
     @Test
     public void testLockScreenShowNotificationsChangeUpdatesNotifications() {
         mLockscreenUserManager.getLockscreenSettingsObserverForTest().onChange(false);
-        verify(mEntryManager, times(1)).updateNotifications();
+        verify(mEntryManager, times(1)).updateNotifications(anyString());
     }
 
     @Test
@@ -138,7 +141,7 @@
     public void testSettingsObserverUpdatesNotifications() {
         when(mDeviceProvisionedController.isDeviceProvisioned()).thenReturn(true);
         mLockscreenUserManager.getSettingsObserverForTest().onChange(false);
-        verify(mEntryManager, times(1)).updateNotifications();
+        verify(mEntryManager, times(1)).updateNotifications(anyString());
     }
 
     @Test
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 de77af8..cb4096c 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationTestHelper.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationTestHelper.java
@@ -42,6 +42,8 @@
 
 import androidx.test.InstrumentationRegistry;
 
+import com.android.systemui.TestableDependency;
+import com.android.systemui.bubbles.BubbleController;
 import com.android.systemui.bubbles.BubblesTestActivity;
 import com.android.systemui.plugins.statusbar.StatusBarStateController;
 import com.android.systemui.statusbar.notification.collection.NotificationEntry;
@@ -51,6 +53,7 @@
 import com.android.systemui.statusbar.phone.HeadsUpManagerPhone;
 import com.android.systemui.statusbar.phone.KeyguardBypassController;
 import com.android.systemui.statusbar.phone.NotificationGroupManager;
+import com.android.systemui.statusbar.phone.StatusBarWindowController;
 import com.android.systemui.tests.R;
 
 /**
@@ -75,8 +78,11 @@
     private ExpandableNotificationRow mRow;
     private HeadsUpManagerPhone mHeadsUpManager;
 
-    public NotificationTestHelper(Context context) {
+    public NotificationTestHelper(Context context, TestableDependency dependency) {
         mContext = context;
+        dependency.injectMockDependency(NotificationMediaManager.class);
+        dependency.injectMockDependency(BubbleController.class);
+        dependency.injectMockDependency(StatusBarWindowController.class);
         mInstrumentation = InstrumentationRegistry.getInstrumentation();
         StatusBarStateController stateController = mock(StatusBarStateController.class);
         mGroupManager = new NotificationGroupManager(stateController);
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 9e72504..6efa57d 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationViewHierarchyManagerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationViewHierarchyManagerTest.java
@@ -103,7 +103,7 @@
         mDependency.injectTestDependency(VisualStabilityManager.class, mVisualStabilityManager);
         mDependency.injectTestDependency(ShadeController.class, mShadeController);
 
-        mHelper = new NotificationTestHelper(mContext);
+        mHelper = new NotificationTestHelper(mContext, mDependency);
 
         when(mEntryManager.getNotificationData()).thenReturn(mNotificationData);
 
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/AboveShelfObserverTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/AboveShelfObserverTest.java
index db2c878..4103ede 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/AboveShelfObserverTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/AboveShelfObserverTest.java
@@ -47,7 +47,7 @@
     @Before
     public void setUp() throws Exception {
         com.android.systemui.util.Assert.sMainLooper = TestableLooper.get(this).getLooper();
-        mNotificationTestHelper = new NotificationTestHelper(getContext());
+        mNotificationTestHelper = new NotificationTestHelper(getContext(), mDependency);
         mHostLayout = new FrameLayout(getContext());
         mObserver = new AboveShelfObserver(mHostLayout);
         ExpandableNotificationRow row = mNotificationTestHelper.createRow();
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/ActivityLaunchAnimatorTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/ActivityLaunchAnimatorTest.java
index 5558393..145a25c 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/ActivityLaunchAnimatorTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/ActivityLaunchAnimatorTest.java
@@ -17,11 +17,8 @@
 package com.android.systemui.statusbar.notification;
 
 import static org.mockito.ArgumentMatchers.any;
-import static org.mockito.ArgumentMatchers.anyInt;
 import static org.mockito.ArgumentMatchers.anyLong;
-import static org.mockito.ArgumentMatchers.anyObject;
 import static org.mockito.Mockito.doAnswer;
-import static org.mockito.Mockito.doReturn;
 import static org.mockito.Mockito.mock;
 import static org.mockito.Mockito.verify;
 import static org.mockito.Mockito.when;
@@ -30,23 +27,20 @@
 import android.test.suitebuilder.annotation.SmallTest;
 import android.testing.AndroidTestingRunner;
 import android.testing.TestableLooper;
-import android.testing.TestableLooper.RunWithLooper;
 import android.view.RemoteAnimationAdapter;
 import android.view.View;
-import android.widget.FrameLayout;
 
 import com.android.systemui.SysuiTestCase;
-import com.android.systemui.statusbar.NotificationTestHelper;
 import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow;
 import com.android.systemui.statusbar.notification.stack.NotificationListContainer;
 import com.android.systemui.statusbar.phone.NotificationPanelView;
 import com.android.systemui.statusbar.phone.StatusBarWindowView;
+import com.android.systemui.statusbar.phone.StatusBarWindowViewController;
 
 import org.junit.Assert;
 import org.junit.Before;
 import org.junit.Test;
 import org.junit.runner.RunWith;
-import org.mockito.stubbing.Answer;
 
 @SmallTest
 @RunWith(AndroidTestingRunner.class)
@@ -55,6 +49,8 @@
 
     private ActivityLaunchAnimator mLaunchAnimator;
     private ActivityLaunchAnimator.Callback mCallback = mock(ActivityLaunchAnimator.Callback.class);
+    private StatusBarWindowViewController mStatusBarWindowViewController = mock(
+            StatusBarWindowViewController.class);
     private StatusBarWindowView mStatusBarWindowView = mock(StatusBarWindowView.class);
     private NotificationListContainer mNotificationContainer
             = mock(NotificationListContainer.class);
@@ -62,10 +58,11 @@
 
     @Before
     public void setUp() throws Exception {
+        when(mStatusBarWindowViewController.getView()).thenReturn(mStatusBarWindowView);
         when(mStatusBarWindowView.getResources()).thenReturn(mContext.getResources());
         when(mCallback.areLaunchAnimationsEnabled()).thenReturn(true);
         mLaunchAnimator = new ActivityLaunchAnimator(
-                mStatusBarWindowView,
+                mStatusBarWindowViewController,
                 mCallback,
                 mock(NotificationPanelView.class),
                 mNotificationContainer);
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 30e02e6..e52a258 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
@@ -28,6 +28,7 @@
 import static org.mockito.ArgumentMatchers.any;
 import static org.mockito.ArgumentMatchers.anyBoolean;
 import static org.mockito.ArgumentMatchers.anyInt;
+import static org.mockito.ArgumentMatchers.anyString;
 import static org.mockito.ArgumentMatchers.eq;
 import static org.mockito.Mockito.atLeastOnce;
 import static org.mockito.Mockito.doAnswer;
@@ -41,7 +42,6 @@
 import android.app.Notification;
 import android.app.NotificationManager;
 import android.app.PendingIntent;
-import android.content.Context;
 import android.content.Intent;
 import android.graphics.drawable.Icon;
 import android.os.Handler;
@@ -69,6 +69,7 @@
 import com.android.systemui.statusbar.NotificationLifetimeExtender;
 import com.android.systemui.statusbar.NotificationListener;
 import com.android.systemui.statusbar.NotificationLockscreenUserManager;
+import com.android.systemui.statusbar.NotificationMediaManager;
 import com.android.systemui.statusbar.NotificationPresenter;
 import com.android.systemui.statusbar.NotificationRemoteInputManager;
 import com.android.systemui.statusbar.NotificationRemoveInterceptor;
@@ -80,6 +81,7 @@
 import com.android.systemui.statusbar.notification.collection.NotificationEntry;
 import com.android.systemui.statusbar.notification.collection.NotificationRowBinder;
 import com.android.systemui.statusbar.notification.collection.NotificationRowBinderImpl;
+import com.android.systemui.statusbar.notification.logging.NotifLog;
 import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow;
 import com.android.systemui.statusbar.notification.row.NotificationContentInflater.InflationFlag;
 import com.android.systemui.statusbar.notification.row.NotificationGutsManager;
@@ -145,8 +147,9 @@
     private class TestableNotificationEntryManager extends NotificationEntryManager {
         private final CountDownLatch mCountDownLatch;
 
-        TestableNotificationEntryManager(Context context) {
-            super(context);
+        TestableNotificationEntryManager() {
+            super(new NotificationData(mock(NotificationSectionsFeatureManager.class),
+                    mock(NotifLog.class)), mock(NotifLog.class));
             mCountDownLatch = new CountDownLatch(1);
         }
 
@@ -225,6 +228,7 @@
         mDependency.injectTestDependency(MetricsLogger.class, mMetricsLogger);
         mDependency.injectTestDependency(SmartReplyController.class, mSmartReplyController);
         mDependency.injectTestDependency(KeyguardEnvironment.class, mEnvironment);
+        mDependency.injectMockDependency(NotificationMediaManager.class);
 
         mCountDownLatch = new CountDownLatch(1);
 
@@ -250,7 +254,7 @@
 
         mEntry.expandedIcon = mock(StatusBarIconView.class);
 
-        mEntryManager = new TestableNotificationEntryManager(mContext);
+        mEntryManager = new TestableNotificationEntryManager();
         Dependency.get(InitController.class).executePostInitTasks();
         mEntryManager.setUpWithPresenter(mPresenter, mListContainer, mHeadsUpManager);
         mEntryManager.addNotificationEntryListener(mEntryListener);
@@ -258,7 +262,9 @@
 
         NotificationRowBinderImpl notificationRowBinder =
                 new NotificationRowBinderImpl(mContext, true, /* allowLongPress */
-                        mock(KeyguardBypassController.class), mock(StatusBarStateController.class));
+                        mock(KeyguardBypassController.class),
+                        mock(StatusBarStateController.class),
+                        mock(NotifLog.class));
         notificationRowBinder.setUpWithPresenter(
                 mPresenter, mListContainer, mHeadsUpManager, mEntryManager, mBindCallback);
         notificationRowBinder.setNotificationClicker(mock(NotificationClicker.class));
@@ -349,7 +355,7 @@
         // Ensure that update callbacks happen in correct order
         InOrder order = inOrder(mEntryListener, notifData, mPresenter, mEntryListener);
         order.verify(mEntryListener).onPreEntryUpdated(mEntry);
-        order.verify(notifData).filterAndSort();
+        order.verify(notifData).filterAndSort(anyString());
         order.verify(mPresenter).updateNotificationViews();
         order.verify(mEntryListener).onPostEntryUpdated(mEntry);
 
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 edd0a10..45e1721 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
@@ -42,6 +42,7 @@
 import com.android.systemui.SysuiTestCase;
 import com.android.systemui.plugins.statusbar.StatusBarStateController;
 import com.android.systemui.statusbar.NotificationEntryBuilder;
+import com.android.systemui.statusbar.NotificationLockscreenUserManager;
 import com.android.systemui.statusbar.NotificationTestHelper;
 import com.android.systemui.statusbar.notification.collection.NotificationData;
 import com.android.systemui.statusbar.notification.collection.NotificationEntry;
@@ -94,10 +95,11 @@
         mDependency.injectTestDependency(NotificationGroupManager.class,
                 new NotificationGroupManager(mock(StatusBarStateController.class)));
         mDependency.injectMockDependency(ShadeController.class);
+        mDependency.injectMockDependency(NotificationLockscreenUserManager.class);
         mDependency.injectTestDependency(NotificationData.KeyguardEnvironment.class, mEnvironment);
         when(mEnvironment.isDeviceProvisioned()).thenReturn(true);
         when(mEnvironment.isNotificationForCurrentProfiles(any())).thenReturn(true);
-        mRow = new NotificationTestHelper(getContext()).createRow();
+        mRow = new NotificationTestHelper(getContext(), mDependency).createRow();
         mNotificationFilter = new NotificationFilter();
     }
 
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 8d496a7..170c661 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
@@ -21,6 +21,7 @@
 
 import static org.mockito.ArgumentMatchers.anyInt;
 import static org.mockito.ArgumentMatchers.anyString;
+import static org.mockito.Mockito.mock;
 import static org.mockito.Mockito.never;
 import static org.mockito.Mockito.times;
 import static org.mockito.Mockito.verify;
@@ -41,11 +42,14 @@
 import com.android.systemui.R;
 import com.android.systemui.SysuiTestCase;
 import com.android.systemui.statusbar.NotificationEntryBuilder;
+import com.android.systemui.statusbar.NotificationLockscreenUserManager;
 import com.android.systemui.statusbar.notification.collection.NotificationData;
 import com.android.systemui.statusbar.notification.collection.NotificationEntry;
+import com.android.systemui.statusbar.notification.logging.NotifLog;
 import com.android.systemui.statusbar.notification.stack.NotificationListContainer;
 import com.android.systemui.statusbar.policy.DeviceProvisionedController;
 import com.android.systemui.statusbar.policy.DeviceProvisionedController.DeviceProvisionedListener;
+import com.android.systemui.util.DeviceConfigProxyFake;
 
 import org.junit.Before;
 import org.junit.Test;
@@ -73,13 +77,16 @@
     private DeviceProvisionedListener mProvisionedListener;
 
     // TODO: Remove this once EntryManager no longer needs to be mocked
-    private NotificationData mNotificationData = new NotificationData(mContext);
+    private NotificationData mNotificationData =
+            new NotificationData(new NotificationSectionsFeatureManager(
+                    new DeviceConfigProxyFake(), mContext), mock(NotifLog.class));
 
     private int mNextNotifId = 0;
 
     @Before
     public void setUp() {
         MockitoAnnotations.initMocks(this);
+        mDependency.injectMockDependency(NotificationLockscreenUserManager.class);
 
         when(mEntryManager.getNotificationData()).thenReturn(mNotificationData);
 
@@ -110,7 +117,7 @@
     @Test
     public void testCallUpdateNotificationsOnDeviceProvisionedChange() {
         mProvisionedListener.onDeviceProvisionedChanged();
-        verify(mEntryManager).updateNotifications();
+        verify(mEntryManager).updateNotifications(anyString());
     }
 
     @Test
@@ -130,8 +137,8 @@
 
         // THEN the app op is added to the entry
         assertTrue(entry.mActiveAppOps.contains(AppOpsManager.OP_CAMERA));
-        // THEN updateNotifications() is called
-        verify(mEntryManager, times(1)).updateNotifications();
+        // THEN updateNotifications(TEST) is called
+        verify(mEntryManager, times(1)).updateNotifications(anyString());
     }
 
     @Test
@@ -143,8 +150,8 @@
         // WHEN An unrelated notification gets a new app op
         mController.updateNotificationsForAppOp(AppOpsManager.OP_CAMERA, 1000, "pkg", true);
 
-        // THEN We never call updateNotifications()
-        verify(mEntryManager, never()).updateNotifications();
+        // THEN We never call updateNotifications(TEST)
+        verify(mEntryManager, never()).updateNotifications(anyString());
     }
 
     @Test
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/NotificationSectionsFeatureManagerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/NotificationSectionsFeatureManagerTest.kt
new file mode 100644
index 0000000..b3d0d22
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/NotificationSectionsFeatureManagerTest.kt
@@ -0,0 +1,69 @@
+/*
+ * 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.provider.DeviceConfig
+import android.provider.Settings
+import android.provider.Settings.Secure.NOTIFICATION_NEW_INTERRUPTION_MODEL
+import android.testing.AndroidTestingRunner
+
+import androidx.test.filters.SmallTest
+
+import com.android.internal.config.sysui.SystemUiDeviceConfigFlags.NOTIFICATIONS_USE_PEOPLE_FILTERING
+import com.android.systemui.SysuiTestCase
+import com.android.systemui.util.DeviceConfigProxyFake
+
+import org.junit.Assert.assertFalse
+import org.junit.Assert.assertTrue
+import org.junit.Before
+import org.junit.Test
+import org.junit.runner.RunWith
+
+@RunWith(AndroidTestingRunner::class)
+@SmallTest
+class NotificationSectionsFeatureManagerTest : SysuiTestCase() {
+    var manager: NotificationSectionsFeatureManager? = null
+    val proxyFake = DeviceConfigProxyFake()
+
+    @Before
+    public fun setup() {
+        Settings.Secure.putInt(mContext.getContentResolver(),
+        NOTIFICATION_NEW_INTERRUPTION_MODEL, 1)
+        manager = NotificationSectionsFeatureManager(proxyFake, mContext)
+        manager!!.clearCache()
+    }
+
+    @Test
+    public fun testPeopleFilteringOff_newInterruptionModelOn() {
+        proxyFake.setProperty(
+                DeviceConfig.NAMESPACE_SYSTEMUI, NOTIFICATIONS_USE_PEOPLE_FILTERING, "false", false)
+
+        assertFalse("People filtering should be disabled", manager!!.isFilteringEnabled())
+        assertTrue("Expecting 2 buckets when people filtering is disabled",
+                manager!!.getNumberOfBuckets() == 2)
+    }
+
+    @Test
+    public fun testPeopleFilteringOn_newInterruptionModelOn() {
+        proxyFake.setProperty(
+                DeviceConfig.NAMESPACE_SYSTEMUI, NOTIFICATIONS_USE_PEOPLE_FILTERING, "true", false)
+
+        assertTrue("People filtering should be enabled", manager!!.isFilteringEnabled())
+        assertTrue("Expecting 3 buckets when people filtering is enabled",
+                manager!!.getNumberOfBuckets() == 3)
+    }
+}
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 657ec61d..1be6f61 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
@@ -50,7 +50,6 @@
 import android.app.NotificationManager;
 import android.app.PendingIntent;
 import android.app.Person;
-import android.content.Context;
 import android.content.Intent;
 import android.content.pm.IPackageManager;
 import android.content.pm.PackageManager;
@@ -75,10 +74,13 @@
 import com.android.systemui.SysuiTestCase;
 import com.android.systemui.plugins.statusbar.StatusBarStateController;
 import com.android.systemui.statusbar.NotificationEntryBuilder;
+import com.android.systemui.statusbar.NotificationLockscreenUserManager;
 import com.android.systemui.statusbar.NotificationTestHelper;
 import com.android.systemui.statusbar.RankingBuilder;
 import com.android.systemui.statusbar.SbnBuilder;
+import com.android.systemui.statusbar.notification.NotificationSectionsFeatureManager;
 import com.android.systemui.statusbar.notification.collection.NotificationData.KeyguardEnvironment;
+import com.android.systemui.statusbar.notification.logging.NotifLog;
 import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow;
 import com.android.systemui.statusbar.phone.NotificationGroupManager;
 import com.android.systemui.statusbar.phone.ShadeController;
@@ -136,12 +138,14 @@
         mDependency.injectTestDependency(NotificationGroupManager.class,
                 new NotificationGroupManager(mock(StatusBarStateController.class)));
         mDependency.injectMockDependency(ShadeController.class);
+        mDependency.injectMockDependency(NotificationLockscreenUserManager.class);
         mDependency.injectTestDependency(KeyguardEnvironment.class, mEnvironment);
         when(mEnvironment.isDeviceProvisioned()).thenReturn(true);
         when(mEnvironment.isNotificationForCurrentProfiles(any())).thenReturn(true);
-        mNotificationData = new TestableNotificationData(mContext);
-        mNotificationData.updateRanking(mock(NotificationListenerService.RankingMap.class));
-        mRow = new NotificationTestHelper(getContext()).createRow();
+        mNotificationData = new TestableNotificationData(
+                mock(NotificationSectionsFeatureManager.class));
+        mNotificationData.updateRanking(mock(NotificationListenerService.RankingMap.class), "");
+        mRow = new NotificationTestHelper(getContext(), mDependency).createRow();
         Dependency.get(InitController.class).executePostInitTasks();
     }
 
@@ -157,10 +161,11 @@
     @Test
     public void testAllRelevantNotisTaggedWithAppOps() throws Exception {
         mNotificationData.add(mRow.getEntry());
-        ExpandableNotificationRow row2 = new NotificationTestHelper(getContext()).createRow();
+        ExpandableNotificationRow row2 = new NotificationTestHelper(getContext(), mDependency)
+                .createRow();
         mNotificationData.add(row2.getEntry());
         ExpandableNotificationRow diffPkg =
-                new NotificationTestHelper(getContext()).createRow("pkg", 4000,
+                new NotificationTestHelper(getContext(), mDependency).createRow("pkg", 4000,
                         Process.myUserHandle());
         mNotificationData.add(diffPkg.getEntry());
 
@@ -187,7 +192,8 @@
     @Test
     public void testAppOpsRemoval() throws Exception {
         mNotificationData.add(mRow.getEntry());
-        ExpandableNotificationRow row2 = new NotificationTestHelper(getContext()).createRow();
+        ExpandableNotificationRow row2 = new NotificationTestHelper(getContext(), mDependency)
+                .createRow();
         mNotificationData.add(row2.getEntry());
 
         ArraySet<Integer> expectedOps = new ArraySet<>();
@@ -219,7 +225,8 @@
     public void testGetNotificationsForCurrentUser_shouldFilterNonCurrentUserNotifications()
             throws Exception {
         mNotificationData.add(mRow.getEntry());
-        ExpandableNotificationRow row2 = new NotificationTestHelper(getContext()).createRow();
+        ExpandableNotificationRow row2 = new NotificationTestHelper(getContext(), mDependency)
+                .createRow();
         mNotificationData.add(row2.getEntry());
 
         when(mEnvironment.isNotificationForCurrentProfiles(
@@ -631,8 +638,8 @@
     }
 
     public static class TestableNotificationData extends NotificationData {
-        public TestableNotificationData(Context context) {
-            super(context);
+        public TestableNotificationData(NotificationSectionsFeatureManager sectionsFeatureManager) {
+            super(sectionsFeatureManager, mock(NotifLog.class));
         }
 
         public static final String OVERRIDE_RANK = "r";
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRowTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRowTest.java
index c56a168..5e6c963 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRowTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRowTest.java
@@ -82,7 +82,7 @@
     @Before
     public void setUp() throws Exception {
         com.android.systemui.util.Assert.sMainLooper = TestableLooper.get(this).getLooper();
-        mNotificationTestHelper = new NotificationTestHelper(mContext);
+        mNotificationTestHelper = new NotificationTestHelper(mContext, mDependency);
         mGroupRow = mNotificationTestHelper.createGroup();
         mGroupRow.setHeadsUpAnimatingAwayListener(
                 animatingAway -> mHeadsUpAnimatingAway = animatingAway);
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationBlockingHelperManagerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationBlockingHelperManagerTest.java
index 6d64395..444a6e5 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationBlockingHelperManagerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationBlockingHelperManagerTest.java
@@ -27,6 +27,7 @@
 import static org.junit.Assert.assertTrue;
 import static org.mockito.ArgumentMatchers.any;
 import static org.mockito.ArgumentMatchers.anyInt;
+import static org.mockito.ArgumentMatchers.anyString;
 import static org.mockito.Mockito.never;
 import static org.mockito.Mockito.spy;
 import static org.mockito.Mockito.times;
@@ -62,7 +63,6 @@
 @org.junit.runner.RunWith(AndroidTestingRunner.class)
 @TestableLooper.RunWithLooper
 public class NotificationBlockingHelperManagerTest extends SysuiTestCase {
-
     private NotificationBlockingHelperManager mBlockingHelperManager;
 
     private NotificationTestHelper mHelper;
@@ -88,7 +88,7 @@
         mDependency.injectTestDependency(NotificationEntryManager.class, mEntryManager);
         mDependency.injectMockDependency(BubbleController.class);
 
-        mHelper = new NotificationTestHelper(mContext);
+        mHelper = new NotificationTestHelper(mContext, mDependency);
 
         mBlockingHelperManager = new NotificationBlockingHelperManager(mContext);
         // By default, have the shade visible/expanded.
@@ -112,7 +112,7 @@
         assertTrue(mBlockingHelperManager.dismissCurrentBlockingHelper());
         assertTrue(mBlockingHelperManager.isBlockingHelperRowNull());
 
-        verify(mEntryManager, times(0)).updateNotifications();
+        verify(mEntryManager, times(0)).updateNotifications(anyString());
     }
 
     @Test
@@ -125,7 +125,7 @@
         assertTrue(mBlockingHelperManager.dismissCurrentBlockingHelper());
         assertTrue(mBlockingHelperManager.isBlockingHelperRowNull());
 
-        verify(mEntryManager).updateNotifications();
+        verify(mEntryManager).updateNotifications(anyString());
     }
 
     @Test
@@ -267,7 +267,7 @@
         assertTrue(mBlockingHelperManager.dismissCurrentBlockingHelper());
         assertTrue(mBlockingHelperManager.isBlockingHelperRowNull());
 
-        verify(mEntryManager).updateNotifications();
+        verify(mEntryManager).updateNotifications(anyString());
     }
 
     @Test
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationContentInflaterTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationContentInflaterTest.java
index ccadcc3..71c2e11 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationContentInflaterTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationContentInflaterTest.java
@@ -77,7 +77,7 @@
                 .setContentTitle("Title")
                 .setContentText("Text")
                 .setStyle(new Notification.BigTextStyle().bigText("big text"));
-        ExpandableNotificationRow row = new NotificationTestHelper(mContext).createRow(
+        ExpandableNotificationRow row = new NotificationTestHelper(mContext, mDependency).createRow(
                 mBuilder.build());
         mRow = spy(row);
         mNotificationInflater = new NotificationContentInflater(mRow);
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 db6b613..41fe173 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
@@ -62,6 +62,7 @@
 import com.android.internal.logging.MetricsLogger;
 import com.android.systemui.SysuiTestCase;
 import com.android.systemui.plugins.statusbar.NotificationMenuRowPlugin;
+import com.android.systemui.statusbar.NotificationLockscreenUserManager;
 import com.android.systemui.statusbar.NotificationPresenter;
 import com.android.systemui.statusbar.NotificationTestHelper;
 import com.android.systemui.statusbar.notification.NotificationActivityStarter;
@@ -118,9 +119,10 @@
                 mDeviceProvisionedController);
         mDependency.injectTestDependency(MetricsLogger.class, mMetricsLogger);
         mDependency.injectTestDependency(VisualStabilityManager.class, mVisualStabilityManager);
+        mDependency.injectMockDependency(NotificationLockscreenUserManager.class);
         mHandler = Handler.createAsync(mTestableLooper.getLooper());
         mContext.putComponent(StatusBar.class, mStatusBar);
-        mHelper = new NotificationTestHelper(mContext);
+        mHelper = new NotificationTestHelper(mContext, mDependency);
 
         mGutsManager = new NotificationGutsManager(mContext, mVisualStabilityManager);
         mGutsManager.setUpWithPresenter(mPresenter, mStackScroller,
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/wrapper/NotificationCustomViewWrapperTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/wrapper/NotificationCustomViewWrapperTest.java
index 49a6410..d280f18 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/wrapper/NotificationCustomViewWrapperTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/wrapper/NotificationCustomViewWrapperTest.java
@@ -44,7 +44,7 @@
     @Before
     public void setUp() throws Exception {
         com.android.systemui.util.Assert.sMainLooper = TestableLooper.get(this).getLooper();
-        mRow = new NotificationTestHelper(mContext).createRow();
+        mRow = new NotificationTestHelper(mContext, mDependency).createRow();
     }
 
     @Test
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/wrapper/NotificationMediaTemplateViewWrapperTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/wrapper/NotificationMediaTemplateViewWrapperTest.java
index 4f844f0..4f45f68 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/wrapper/NotificationMediaTemplateViewWrapperTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/wrapper/NotificationMediaTemplateViewWrapperTest.java
@@ -94,7 +94,7 @@
         mNotif = builder.build();
         assertTrue(mNotif.hasMediaSession());
 
-        mRow = new NotificationTestHelper(mContext).createRow(mNotif);
+        mRow = new NotificationTestHelper(mContext, mDependency).createRow(mNotif);
 
         RemoteViews views = new RemoteViews(mContext.getPackageName(),
                 com.android.internal.R.layout.notification_template_material_big_media);
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/wrapper/NotificationViewWrapperTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/wrapper/NotificationViewWrapperTest.java
index 5463159..14e2fde 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/wrapper/NotificationViewWrapperTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/wrapper/NotificationViewWrapperTest.java
@@ -50,7 +50,7 @@
     public void setup() throws Exception {
         Assert.sMainLooper = TestableLooper.get(this).getLooper();
         mView = mock(View.class);
-        mRow = new NotificationTestHelper(getContext()).createRow();
+        mRow = new NotificationTestHelper(getContext(), mDependency).createRow();
         mNotificationViewWrapper = new TestableNotificationViewWrapper(mContext, mView, mRow);
     }
 
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/NotificationChildrenContainerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/NotificationChildrenContainerTest.java
index 22d2585..ddd2884e 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/NotificationChildrenContainerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/NotificationChildrenContainerTest.java
@@ -45,7 +45,7 @@
     @Before
     public void setUp() throws Exception {
         com.android.systemui.util.Assert.sMainLooper = TestableLooper.get(this).getLooper();
-        mNotificationTestHelper = new NotificationTestHelper(mContext);
+        mNotificationTestHelper = new NotificationTestHelper(mContext, mDependency);
         mGroup = mNotificationTestHelper.createGroup();
         mChildrenContainer = mGroup.getChildrenContainer();
     }
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/NotificationRoundnessManagerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/NotificationRoundnessManagerTest.java
index addceb5..34a309f 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/NotificationRoundnessManagerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/NotificationRoundnessManagerTest.java
@@ -32,10 +32,12 @@
 import com.android.systemui.SysuiTestCase;
 import com.android.systemui.plugins.statusbar.StatusBarStateController;
 import com.android.systemui.statusbar.NotificationTestHelper;
+import com.android.systemui.statusbar.notification.NotificationSectionsFeatureManager;
 import com.android.systemui.statusbar.notification.collection.NotificationEntry;
 import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow;
 import com.android.systemui.statusbar.notification.row.ExpandableView;
 import com.android.systemui.statusbar.phone.KeyguardBypassController;
+import com.android.systemui.util.DeviceConfigProxy;
 
 import org.junit.Assert;
 import org.junit.Before;
@@ -64,9 +66,11 @@
     @Before
     public void setUp() throws Exception {
         MockitoAnnotations.initMocks(this);
-        mRoundnessManager = new NotificationRoundnessManager(mBypassController, mContext);
+        mRoundnessManager = new NotificationRoundnessManager(
+                mBypassController,
+                new NotificationSectionsFeatureManager(new DeviceConfigProxy(), mContext));
         com.android.systemui.util.Assert.sMainLooper = TestableLooper.get(this).getLooper();
-        NotificationTestHelper testHelper = new NotificationTestHelper(getContext());
+        NotificationTestHelper testHelper = new NotificationTestHelper(getContext(), mDependency);
         mFirst = testHelper.createRow();
         mFirst.setHeadsUpAnimatingAwayListener(animatingAway
                 -> mRoundnessManager.onHeadsupAnimatingAwayChanged(mFirst, animatingAway));
@@ -146,7 +150,8 @@
                 createSection(mFirst, mSecond),
                 createSection(null, null)
         });
-        ExpandableNotificationRow row = new NotificationTestHelper(getContext()).createRow();
+        ExpandableNotificationRow row = new NotificationTestHelper(getContext(), mDependency)
+                .createRow();
         NotificationEntry entry = mock(NotificationEntry.class);
         when(entry.getRow()).thenReturn(row);
 
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayoutTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayoutTest.java
index 31054260..4b82f59 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayoutTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayoutTest.java
@@ -55,8 +55,8 @@
 import com.android.systemui.SysuiTestCase;
 import com.android.systemui.classifier.FalsingManagerFake;
 import com.android.systemui.plugins.statusbar.NotificationMenuRowPlugin;
-import com.android.systemui.plugins.statusbar.StatusBarStateController;
 import com.android.systemui.statusbar.EmptyShadeView;
+import com.android.systemui.statusbar.NotificationLockscreenUserManager;
 import com.android.systemui.statusbar.NotificationPresenter;
 import com.android.systemui.statusbar.NotificationRemoteInputManager;
 import com.android.systemui.statusbar.NotificationShelf;
@@ -65,11 +65,13 @@
 import com.android.systemui.statusbar.SysuiStatusBarStateController;
 import com.android.systemui.statusbar.notification.DynamicPrivacyController;
 import com.android.systemui.statusbar.notification.NotificationEntryManager;
+import com.android.systemui.statusbar.notification.NotificationSectionsFeatureManager;
 import com.android.systemui.statusbar.notification.collection.NotificationData;
 import com.android.systemui.statusbar.notification.collection.NotificationEntry;
 import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow;
 import com.android.systemui.statusbar.notification.row.FooterView;
 import com.android.systemui.statusbar.notification.row.NotificationBlockingHelperManager;
+import com.android.systemui.statusbar.notification.row.NotificationGutsManager;
 import com.android.systemui.statusbar.phone.HeadsUpManagerPhone;
 import com.android.systemui.statusbar.phone.KeyguardBypassController;
 import com.android.systemui.statusbar.phone.NotificationGroupManager;
@@ -79,6 +81,7 @@
 import com.android.systemui.statusbar.phone.StatusBar;
 import com.android.systemui.statusbar.phone.StatusBarTest.TestableNotificationEntryManager;
 import com.android.systemui.statusbar.policy.ConfigurationController;
+import com.android.systemui.util.DeviceConfigProxyFake;
 
 import org.junit.After;
 import org.junit.Before;
@@ -144,11 +147,10 @@
         mDependency.injectMockDependency(ShadeController.class);
         when(mRemoteInputManager.getController()).thenReturn(mRemoteInputController);
 
-        mEntryManager = new TestableNotificationEntryManager(mContext);
+        mEntryManager = new TestableNotificationEntryManager(mNotificationData);
         mDependency.injectTestDependency(NotificationEntryManager.class, mEntryManager);
         Dependency.get(InitController.class).executePostInitTasks();
-        mEntryManager.setUpForTest(mock(NotificationPresenter.class), null, mHeadsUpManager,
-                mNotificationData);
+        mEntryManager.setUpForTest(mock(NotificationPresenter.class), null, mHeadsUpManager);
 
 
         NotificationShelf notificationShelf = mock(NotificationShelf.class);
@@ -166,7 +168,10 @@
                 mock(SysuiStatusBarStateController.class),
                 mHeadsUpManager,
                 mKeyguardBypassController,
-                new FalsingManagerFake());
+                new FalsingManagerFake(),
+                mock(NotificationLockscreenUserManager.class),
+                mock(NotificationGutsManager.class),
+                new NotificationSectionsFeatureManager(new DeviceConfigProxyFake(), mContext));
         mStackScroller = spy(mStackScrollerInternal);
         mStackScroller.setShelf(notificationShelf);
         mStackScroller.setStatusBar(mBar);
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/AutoHideControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/AutoHideControllerTest.java
index f614354..16f02d9 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/AutoHideControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/AutoHideControllerTest.java
@@ -31,6 +31,7 @@
 import android.graphics.Rect;
 import android.testing.AndroidTestingRunner;
 import android.testing.TestableLooper.RunWithLooper;
+import android.view.IWindowManager;
 import android.view.View;
 
 import androidx.test.filters.SmallTest;
@@ -38,6 +39,7 @@
 import com.android.systemui.Dependency;
 import com.android.systemui.SysuiTestCase;
 import com.android.systemui.statusbar.CommandQueue;
+import com.android.systemui.statusbar.NotificationRemoteInputManager;
 
 import org.junit.After;
 import org.junit.Before;
@@ -58,7 +60,8 @@
     public void setUp() {
         mContext.putComponent(CommandQueue.class, mock(CommandQueue.class));
         mAutoHideController =
-                spy(new AutoHideController(mContext, Dependency.get(Dependency.MAIN_HANDLER)));
+                spy(new AutoHideController(mContext, Dependency.get(Dependency.MAIN_HANDLER),
+                        mock(NotificationRemoteInputManager.class), mock(IWindowManager.class)));
         mAutoHideController.mDisplayId = DEFAULT_DISPLAY;
         mAutoHideController.mSystemUiVisibility = View.VISIBLE;
     }
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/HeadsUpAppearanceControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/HeadsUpAppearanceControllerTest.java
index a38094d..0216d2e 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/HeadsUpAppearanceControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/HeadsUpAppearanceControllerTest.java
@@ -38,6 +38,7 @@
 import com.android.systemui.statusbar.notification.NotificationWakeUpCoordinator;
 import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow;
 import com.android.systemui.statusbar.notification.stack.NotificationStackScrollLayout;
+import com.android.systemui.statusbar.policy.KeyguardStateController;
 
 import org.junit.Assert;
 import org.junit.Before;
@@ -61,11 +62,12 @@
     private StatusBarStateController mStatusbarStateController;
     private KeyguardBypassController mBypassController;
     private NotificationWakeUpCoordinator mWakeUpCoordinator;
+    private KeyguardStateController mKeyguardStateController;
 
     @Before
     public void setUp() throws Exception {
         com.android.systemui.util.Assert.sMainLooper = TestableLooper.get(this).getLooper();
-        NotificationTestHelper testHelper = new NotificationTestHelper(getContext());
+        NotificationTestHelper testHelper = new NotificationTestHelper(getContext(), mDependency);
         mFirst = testHelper.createRow();
         mDependency.injectTestDependency(DarkIconDispatcher.class, mDarkIconDispatcher);
         mHeadsUpStatusBarView = new HeadsUpStatusBarView(mContext, mock(View.class),
@@ -75,12 +77,14 @@
         mStatusbarStateController = mock(StatusBarStateController.class);
         mBypassController = mock(KeyguardBypassController.class);
         mWakeUpCoordinator = mock(NotificationWakeUpCoordinator.class);
+        mKeyguardStateController = mock(KeyguardStateController.class);
         mHeadsUpAppearanceController = new HeadsUpAppearanceController(
                 mock(NotificationIconAreaController.class),
                 mHeadsUpManager,
                 mStatusbarStateController,
                 mBypassController,
                 mWakeUpCoordinator,
+                mKeyguardStateController,
                 mHeadsUpStatusBarView,
                 mStackScroller,
                 mPanelView,
@@ -158,6 +162,7 @@
                 mStatusbarStateController,
                 mBypassController,
                 mWakeUpCoordinator,
+                mKeyguardStateController,
                 mHeadsUpStatusBarView,
                 mStackScroller,
                 mPanelView,
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 ef9665a..6fcf550 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
@@ -29,6 +29,7 @@
 
 import androidx.test.filters.SmallTest;
 
+import com.android.systemui.bubbles.BubbleController;
 import com.android.systemui.plugins.statusbar.StatusBarStateController;
 import com.android.systemui.statusbar.AlertingNotificationManager;
 import com.android.systemui.statusbar.AlertingNotificationManagerTest;
@@ -36,6 +37,7 @@
 import com.android.systemui.statusbar.notification.VisualStabilityManager;
 import com.android.systemui.statusbar.notification.collection.NotificationEntry;
 import com.android.systemui.statusbar.policy.AccessibilityManagerWrapper;
+import com.android.systemui.statusbar.policy.ConfigurationController;
 
 import org.junit.Before;
 import org.junit.Rule;
@@ -85,6 +87,9 @@
         when(accessibilityMgr.getRecommendedTimeoutMillis(anyInt(), anyInt()))
                 .thenReturn(TEST_AUTO_DISMISS_TIME);
         when(mVSManager.isReorderingAllowed()).thenReturn(true);
+        mDependency.injectMockDependency(BubbleController.class);
+        mDependency.injectMockDependency(StatusBarWindowController.class);
+        mDependency.injectMockDependency(ConfigurationController.class);
         mHeadsUpManager = new TestableHeadsUpManagerPhone(mContext, mStatusBarWindowView,
                 mGroupManager, mBar, mVSManager, mStatusBarStateController, mBypassController);
         super.setUp();
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/KeyguardBottomAreaTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/KeyguardBottomAreaTest.kt
index 688a6fb..2b091f2 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/KeyguardBottomAreaTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/KeyguardBottomAreaTest.kt
@@ -1,14 +1,11 @@
 package com.android.systemui.statusbar.phone
 
-import androidx.test.filters.SmallTest
 import android.testing.AndroidTestingRunner
 import android.testing.TestableLooper
 import android.view.LayoutInflater
-
+import androidx.test.filters.SmallTest
 import com.android.systemui.R
 import com.android.systemui.SysuiTestCase
-import com.android.systemui.statusbar.KeyguardIndicationController
-
 import org.junit.Before
 import org.junit.Test
 import org.junit.runner.RunWith
@@ -17,7 +14,7 @@
 
 @SmallTest
 @RunWith(AndroidTestingRunner::class)
-@TestableLooper.RunWithLooper
+@TestableLooper.RunWithLooper(setAsMainLooper = true)
 class KeyguardBottomAreaTest : SysuiTestCase() {
 
     @Mock
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/KeyguardBouncerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/KeyguardBouncerTest.java
index 3ba3e28..67b8e07 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/KeyguardBouncerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/KeyguardBouncerTest.java
@@ -89,6 +89,8 @@
     private KeyguardBypassController mKeyguardBypassController;
     @Mock
     private Handler mHandler;
+    @Mock
+    private KeyguardSecurityModel mKeyguardSecurityModel;
 
     private KeyguardBouncer mBouncer;
 
@@ -97,6 +99,10 @@
         com.android.systemui.util.Assert.sMainLooper = TestableLooper.get(this).getLooper();
         MockitoAnnotations.initMocks(this);
         mDependency.injectTestDependency(KeyguardUpdateMonitor.class, mKeyguardUpdateMonitor);
+        mDependency.injectTestDependency(KeyguardSecurityModel.class, mKeyguardSecurityModel);
+        mDependency.injectMockDependency(KeyguardStateController.class);
+        when(mKeyguardSecurityModel.getSecurityMode(anyInt()))
+                .thenReturn(KeyguardSecurityModel.SecurityMode.None);
         DejankUtils.setImmediate(true);
         final ViewGroup container = new FrameLayout(getContext());
         when(mKeyguardHostView.getViewTreeObserver()).thenReturn(mViewTreeObserver);
@@ -306,14 +312,6 @@
     }
 
     @Test
-    public void testNeedsFullscreenBouncer_asksKeyguardView() {
-        mBouncer.ensureView();
-        mBouncer.needsFullscreenBouncer();
-        verify(mKeyguardHostView).getSecurityMode();
-        verify(mKeyguardHostView, never()).getCurrentSecurityMode();
-    }
-
-    @Test
     public void testIsFullscreenBouncer_asksKeyguardView() {
         mBouncer.ensureView();
         mBouncer.isFullscreenBouncer();
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/LightBarTransitionsControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/LightBarTransitionsControllerTest.java
index 93fdce1..b1580ee 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/LightBarTransitionsControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/LightBarTransitionsControllerTest.java
@@ -28,8 +28,10 @@
 import androidx.test.filters.SmallTest;
 
 import com.android.systemui.SysuiTestCase;
+import com.android.systemui.plugins.statusbar.StatusBarStateController;
 import com.android.systemui.statusbar.CommandQueue;
 import com.android.systemui.statusbar.phone.LightBarTransitionsController.DarkIntensityApplier;
+import com.android.systemui.statusbar.policy.KeyguardStateController;
 
 import org.junit.Before;
 import org.junit.Test;
@@ -50,6 +52,8 @@
     public void setup() {
         MockitoAnnotations.initMocks(this);
         mContext.putComponent(CommandQueue.class, mock(CommandQueue.class));
+        mDependency.injectMockDependency(KeyguardStateController.class);
+        mDependency.injectMockDependency(StatusBarStateController.class);
         mLightBarTransitionsController = new LightBarTransitionsController(mContext, mApplier);
     }
 
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NavigationBarButtonTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NavigationBarButtonTest.java
index 81e8abf..098a69f 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NavigationBarButtonTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NavigationBarButtonTest.java
@@ -35,7 +35,10 @@
 
 import com.android.systemui.SysuiTestCase;
 import com.android.systemui.SysuiTestableContext;
+import com.android.systemui.assist.AssistManager;
+import com.android.systemui.recents.OverviewProxyService;
 import com.android.systemui.statusbar.CommandQueue;
+import com.android.systemui.statusbar.policy.KeyguardStateController;
 
 import org.junit.After;
 import org.junit.Before;
@@ -63,6 +66,9 @@
                 (SysuiTestableContext) mContext.createDisplayContext(display);
         context.putComponent(CommandQueue.class, mock(CommandQueue.class));
 
+        mDependency.injectMockDependency(AssistManager.class);
+        mDependency.injectMockDependency(OverviewProxyService.class);
+        mDependency.injectMockDependency(KeyguardStateController.class);
         mNavBar = new NavigationBarView(context, null);
     }
 
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NavigationBarContextTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NavigationBarContextTest.java
index be69f5f..6433376 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NavigationBarContextTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NavigationBarContextTest.java
@@ -33,6 +33,7 @@
 import androidx.test.runner.AndroidJUnit4;
 
 import com.android.systemui.SysuiTestCase;
+import com.android.systemui.assist.AssistManager;
 import com.android.systemui.statusbar.policy.KeyButtonDrawable;
 
 import org.junit.Before;
@@ -60,6 +61,8 @@
 
     @Before
     public void setup() {
+        mDependency.injectMockDependency(AssistManager.class);
+
         mGroup = new ContextualButtonGroup(GROUP_ID);
         mBtn0 = new ContextualButton(BUTTON_0_ID, ICON_RES_ID);
         mBtn1 = new ContextualButton(BUTTON_1_ID, ICON_RES_ID);
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NavigationBarInflaterViewTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NavigationBarInflaterViewTest.java
index cec7feb..991e495 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NavigationBarInflaterViewTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NavigationBarInflaterViewTest.java
@@ -31,6 +31,8 @@
 import androidx.test.filters.SmallTest;
 
 import com.android.systemui.SysuiTestCase;
+import com.android.systemui.assist.AssistManager;
+import com.android.systemui.recents.OverviewProxyService;
 import com.android.systemui.statusbar.CommandQueue;
 
 import org.junit.After;
@@ -51,6 +53,9 @@
     @Before
     public void setUp() {
         mContext.putComponent(CommandQueue.class, mock(CommandQueue.class));
+        mDependency.injectMockDependency(AssistManager.class);
+        mDependency.injectMockDependency(OverviewProxyService.class);
+        mDependency.injectMockDependency(NavigationModeController.class);
 
         mNavBarInflaterView = spy(new NavigationBarInflaterView(mContext, null));
         doNothing().when(mNavBarInflaterView).createInflaters();
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NavigationBarTransitionsTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NavigationBarTransitionsTest.java
index bb109bd..1e9378a 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NavigationBarTransitionsTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NavigationBarTransitionsTest.java
@@ -28,7 +28,11 @@
 import androidx.test.filters.SmallTest;
 
 import com.android.systemui.SysuiTestCase;
+import com.android.systemui.assist.AssistManager;
+import com.android.systemui.plugins.statusbar.StatusBarStateController;
+import com.android.systemui.recents.OverviewProxyService;
 import com.android.systemui.statusbar.CommandQueue;
+import com.android.systemui.statusbar.policy.KeyguardStateController;
 
 import org.junit.Before;
 import org.junit.Test;
@@ -44,6 +48,12 @@
     @Before
     public void setup() {
         mDependency.injectMockDependency(IWindowManager.class);
+        mDependency.injectMockDependency(AssistManager.class);
+        mDependency.injectMockDependency(OverviewProxyService.class);
+        mDependency.injectMockDependency(NavigationModeController.class);
+        mDependency.injectMockDependency(StatusBarStateController.class);
+        mDependency.injectMockDependency(KeyguardStateController.class);
+
         mContext.putComponent(CommandQueue.class, mock(CommandQueue.class));
         NavigationBarView navBar = spy(new NavigationBarView(mContext, null));
         when(navBar.getCurrentView()).thenReturn(navBar);
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 a0d264d..2254234 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
@@ -33,6 +33,7 @@
 import androidx.test.filters.SmallTest;
 
 import com.android.systemui.SysuiTestCase;
+import com.android.systemui.bubbles.BubbleController;
 import com.android.systemui.plugins.statusbar.StatusBarStateController;
 import com.android.systemui.statusbar.notification.NotificationEntryListener;
 import com.android.systemui.statusbar.notification.NotificationEntryManager;
@@ -71,6 +72,7 @@
 
     @Before
     public void setup() {
+        mDependency.injectMockDependency(BubbleController.class);
         mHeadsUpManager = new HeadsUpManager(mContext) {};
 
         when(mNotificationEntryManager.getPendingNotificationsIterator())
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 dd274c7..493b74d 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
@@ -30,6 +30,7 @@
 import androidx.test.filters.SmallTest;
 
 import com.android.systemui.SysuiTestCase;
+import com.android.systemui.bubbles.BubbleController;
 import com.android.systemui.plugins.statusbar.StatusBarStateController;
 import com.android.systemui.statusbar.notification.collection.NotificationEntry;
 import com.android.systemui.statusbar.policy.HeadsUpManager;
@@ -57,6 +58,7 @@
 
     @Before
     public void setup() {
+        mDependency.injectMockDependency(BubbleController.class);
         initializeGroupManager();
     }
 
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 f1da4e8..2c19037 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
@@ -40,8 +40,8 @@
 import com.android.keyguard.KeyguardUpdateMonitor;
 import com.android.systemui.SystemUIFactory;
 import com.android.systemui.SysuiTestCase;
-import com.android.systemui.doze.DozeLog;
 import com.android.systemui.classifier.FalsingManagerFake;
+import com.android.systemui.doze.DozeLog;
 import com.android.systemui.plugins.FalsingManager;
 import com.android.systemui.plugins.statusbar.StatusBarStateController;
 import com.android.systemui.shared.plugins.PluginManager;
@@ -52,10 +52,15 @@
 import com.android.systemui.statusbar.StatusBarStateControllerImpl;
 import com.android.systemui.statusbar.SysuiStatusBarStateController;
 import com.android.systemui.statusbar.notification.DynamicPrivacyController;
+import com.android.systemui.statusbar.notification.NotificationEntryManager;
+import com.android.systemui.statusbar.notification.NotificationSectionsFeatureManager;
 import com.android.systemui.statusbar.notification.NotificationWakeUpCoordinator;
+import com.android.systemui.statusbar.notification.collection.NotificationData;
+import com.android.systemui.statusbar.notification.logging.NotifLog;
 import com.android.systemui.statusbar.notification.stack.NotificationRoundnessManager;
 import com.android.systemui.statusbar.notification.stack.NotificationStackScrollLayout;
 import com.android.systemui.statusbar.policy.ConfigurationController;
+import com.android.systemui.statusbar.policy.KeyguardStateController;
 import com.android.systemui.statusbar.policy.ZenModeController;
 import com.android.systemui.util.InjectionInflationController;
 
@@ -122,8 +127,6 @@
         mDependency.injectTestDependency(StatusBarStateController.class,
                 mStatusBarStateController);
         mDependency.injectTestDependency(KeyguardUpdateMonitor.class, mUpdateMonitor);
-        mDependency.injectMockDependency(ShadeController.class);
-        mDependency.injectMockDependency(NotificationLockscreenUserManager.class);
         mDependency.injectMockDependency(ConfigurationController.class);
         mDependency.injectMockDependency(ZenModeController.class);
         NotificationWakeUpCoordinator coordinator =
@@ -139,7 +142,7 @@
                 mStatusBarStateController,
                 new FalsingManagerFake());
         mNotificationPanelView = new TestableNotificationPanelView(coordinator, expansionHandler,
-                mKeyguardBypassController);
+                mKeyguardBypassController, mStatusBarStateController);
         mNotificationPanelView.setHeadsUpManager(mHeadsUpManager);
         mNotificationPanelView.setBar(mPanelBar);
 
@@ -216,13 +219,27 @@
     private class TestableNotificationPanelView extends NotificationPanelView {
         TestableNotificationPanelView(NotificationWakeUpCoordinator coordinator,
                 PulseExpansionHandler expansionHandler,
-                KeyguardBypassController bypassController) {
-            super(NotificationPanelViewTest.this.mContext, null,
+                KeyguardBypassController bypassController,
+                SysuiStatusBarStateController statusBarStateController) {
+            super(
+                    NotificationPanelViewTest.this.mContext,
+                    null,
                     new InjectionInflationController(
                             SystemUIFactory.getInstance().getRootComponent()),
-                    coordinator, expansionHandler, mock(DynamicPrivacyController.class),
+                    coordinator,
+                    expansionHandler,
+                    mock(DynamicPrivacyController.class),
                     bypassController,
-                    mFalsingManager, mock(PluginManager.class), mock(DozeLog.class));
+                    mFalsingManager,
+                    mock(PluginManager.class),
+                    mock(ShadeController.class),
+                    mock(NotificationLockscreenUserManager.class),
+                    new NotificationEntryManager(new NotificationData(mock(
+                            NotificationSectionsFeatureManager.class), mock(NotifLog.class)),
+                            mock(NotifLog.class)),
+                    mock(KeyguardStateController.class),
+                    statusBarStateController,
+                    mock(DozeLog.class));
             mNotificationStackScroller = mNotificationStackScrollLayout;
             mKeyguardStatusView = NotificationPanelViewTest.this.mKeyguardStatusView;
             mKeyguardStatusBar = NotificationPanelViewTest.this.mKeyguardStatusBar;
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManagerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManagerTest.java
index c3b25ce..3e07cff 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManagerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManagerTest.java
@@ -45,6 +45,7 @@
 import com.android.systemui.plugins.ActivityStarter.OnDismissAction;
 import com.android.systemui.plugins.FalsingManager;
 import com.android.systemui.plugins.statusbar.StatusBarStateController;
+import com.android.systemui.statusbar.NotificationMediaManager;
 import com.android.systemui.statusbar.SysuiStatusBarStateController;
 import com.android.systemui.statusbar.policy.KeyguardStateController;
 
@@ -92,6 +93,7 @@
         MockitoAnnotations.initMocks(this);
         mDependency.injectMockDependency(StatusBarWindowController.class);
         mDependency.injectMockDependency(KeyguardUpdateMonitor.class);
+        mDependency.injectMockDependency(NotificationMediaManager.class);
         mDependency.injectTestDependency(StatusBarStateController.class, mStatusBarStateController);
         mDependency.injectTestDependency(KeyguardStateController.class, mKeyguardStateController);
         when(mLockIconContainer.getParent()).thenReturn(mock(ViewGroup.class));
@@ -227,6 +229,31 @@
         verify(mStatusBar, never()).animateKeyguardUnoccluding();
     }
 
+    @Test
+    public void testHiding_cancelsGoneRunnable() {
+        OnDismissAction action = mock(OnDismissAction.class);
+        Runnable cancelAction = mock(Runnable.class);
+        mStatusBarKeyguardViewManager.dismissWithAction(action, cancelAction,
+                true /* afterKeyguardGone */);
+
+        mStatusBarKeyguardViewManager.hideBouncer(true);
+        mStatusBarKeyguardViewManager.hide(0, 30);
+        verify(action, never()).onDismiss();
+        verify(cancelAction).run();
+    }
+
+    @Test
+    public void testHiding_doesntCancelWhenShowing() {
+        OnDismissAction action = mock(OnDismissAction.class);
+        Runnable cancelAction = mock(Runnable.class);
+        mStatusBarKeyguardViewManager.dismissWithAction(action, cancelAction,
+                true /* afterKeyguardGone */);
+
+        mStatusBarKeyguardViewManager.hide(0, 30);
+        verify(action).onDismiss();
+        verify(cancelAction, never()).run();
+    }
+
     private class TestableStatusBarKeyguardViewManager extends StatusBarKeyguardViewManager {
 
         public TestableStatusBarKeyguardViewManager(Context context,
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarNotificationActivityStarterTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarNotificationActivityStarterTest.java
index 266abcf..d8a68b0 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarNotificationActivityStarterTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarNotificationActivityStarterTest.java
@@ -140,7 +140,7 @@
         when(mContentIntent.getCreatorUserHandle()).thenReturn(UserHandle.of(1));
         when(mContentIntent.getIntent()).thenReturn(mContentIntentInner);
 
-        mNotificationTestHelper = new NotificationTestHelper(mContext);
+        mNotificationTestHelper = new NotificationTestHelper(mContext, mDependency);
 
         // Create standard notification with contentIntent
         mNotificationRow = mNotificationTestHelper.createRow();
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 24ec109..210c9d6 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
@@ -35,21 +35,37 @@
 import com.android.internal.logging.MetricsLogger;
 import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
 import com.android.internal.logging.testing.FakeMetricsLogger;
+import com.android.systemui.InitController;
 import com.android.systemui.SysuiTestCase;
+import com.android.systemui.plugins.statusbar.StatusBarStateController;
 import com.android.systemui.statusbar.CommandQueue;
 import com.android.systemui.statusbar.NotificationEntryBuilder;
+import com.android.systemui.statusbar.NotificationLockscreenUserManager;
+import com.android.systemui.statusbar.NotificationMediaManager;
+import com.android.systemui.statusbar.NotificationRemoteInputManager;
+import com.android.systemui.statusbar.NotificationViewHierarchyManager;
+import com.android.systemui.statusbar.RemoteInputController;
+import com.android.systemui.statusbar.SysuiStatusBarStateController;
 import com.android.systemui.statusbar.notification.ActivityLaunchAnimator;
 import com.android.systemui.statusbar.notification.DynamicPrivacyController;
 import com.android.systemui.statusbar.notification.NotificationAlertingManager;
+import com.android.systemui.statusbar.notification.NotificationEntryManager;
+import com.android.systemui.statusbar.notification.NotificationInterruptionStateProvider;
+import com.android.systemui.statusbar.notification.VisualStabilityManager;
+import com.android.systemui.statusbar.notification.collection.NotificationData;
 import com.android.systemui.statusbar.notification.collection.NotificationEntry;
 import com.android.systemui.statusbar.notification.collection.NotificationRowBinderImpl;
 import com.android.systemui.statusbar.notification.row.ActivatableNotificationView;
+import com.android.systemui.statusbar.notification.row.NotificationGutsManager;
 import com.android.systemui.statusbar.notification.stack.NotificationListContainer;
+import com.android.systemui.statusbar.policy.KeyguardStateController;
 
 import org.junit.Before;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 
+import java.util.ArrayList;
+
 @SmallTest
 @RunWith(AndroidTestingRunner.class)
 @RunWithLooper()
@@ -63,11 +79,33 @@
 
     @Before
     public void setup() {
+        NotificationRemoteInputManager notificationRemoteInputManager =
+                mock(NotificationRemoteInputManager.class);
+        when(notificationRemoteInputManager.getController())
+                .thenReturn(mock(RemoteInputController.class));
         mMetricsLogger = new FakeMetricsLogger();
         mDependency.injectTestDependency(MetricsLogger.class, mMetricsLogger);
         mCommandQueue = new CommandQueue(mContext);
         mContext.putComponent(CommandQueue.class, mCommandQueue);
+        mDependency.injectTestDependency(StatusBarStateController.class,
+                mock(SysuiStatusBarStateController.class));
         mDependency.injectTestDependency(ShadeController.class, mShadeController);
+        mDependency.injectTestDependency(NotificationRemoteInputManager.class,
+                notificationRemoteInputManager);
+        mDependency.injectMockDependency(NotificationViewHierarchyManager.class);
+        mDependency.injectMockDependency(NotificationRemoteInputManager.Callback.class);
+        mDependency.injectMockDependency(NotificationLockscreenUserManager.class);
+        mDependency.injectMockDependency(NotificationInterruptionStateProvider.class);
+        mDependency.injectMockDependency(NotificationMediaManager.class);
+        mDependency.injectMockDependency(VisualStabilityManager.class);
+        mDependency.injectMockDependency(NotificationGutsManager.class);
+        mDependency.injectMockDependency(StatusBarWindowController.class);
+        mDependency.injectMockDependency(InitController.class);
+        NotificationData notificationData = mock(NotificationData.class);
+        when(notificationData.getNotificationsForCurrentUser()).thenReturn(new ArrayList<>());
+        NotificationEntryManager entryManager =
+                mDependency.injectMockDependency(NotificationEntryManager.class);
+        when(entryManager.getNotificationData()).thenReturn(notificationData);
 
         StatusBarWindowView statusBarWindowView = mock(StatusBarWindowView.class);
         when(statusBarWindowView.getResources()).thenReturn(mContext.getResources());
@@ -77,7 +115,7 @@
                 mock(DozeScrimController.class), mock(ScrimController.class),
                 mock(ActivityLaunchAnimator.class), mock(DynamicPrivacyController.class),
                 mock(NotificationAlertingManager.class),
-                mock(NotificationRowBinderImpl.class));
+                mock(NotificationRowBinderImpl.class), mock(KeyguardStateController.class));
     }
 
     @Test
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarRemoteInputCallbackTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarRemoteInputCallbackTest.java
index 4b6ca56..a65f5a5 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarRemoteInputCallbackTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarRemoteInputCallbackTest.java
@@ -24,18 +24,19 @@
 import static org.mockito.internal.verification.VerificationModeFactory.times;
 
 import android.content.Intent;
-import android.os.UserManager;
 import android.testing.AndroidTestingRunner;
 import android.testing.TestableLooper;
 
 import androidx.test.filters.SmallTest;
 
 import com.android.systemui.SysuiTestCase;
+import com.android.systemui.plugins.ActivityStarter;
 import com.android.systemui.statusbar.CommandQueue;
 import com.android.systemui.statusbar.NotificationLockscreenUserManager;
-import com.android.systemui.statusbar.NotificationPresenter;
+import com.android.systemui.statusbar.SysuiStatusBarStateController;
 import com.android.systemui.statusbar.notification.NotificationEntryManager;
 import com.android.systemui.statusbar.policy.DeviceProvisionedController;
+import com.android.systemui.statusbar.policy.KeyguardStateController;
 
 import org.junit.Before;
 import org.junit.Test;
@@ -47,14 +48,13 @@
 @RunWith(AndroidTestingRunner.class)
 @TestableLooper.RunWithLooper
 public class StatusBarRemoteInputCallbackTest extends SysuiTestCase {
-    @Mock private NotificationPresenter mPresenter;
-    @Mock private UserManager mUserManager;
-
-    // Dependency mocks:
     @Mock private NotificationEntryManager mEntryManager;
     @Mock private DeviceProvisionedController mDeviceProvisionedController;
     @Mock private ShadeController mShadeController;
     @Mock private NotificationLockscreenUserManager mNotificationLockscreenUserManager;
+    @Mock private KeyguardStateController mKeyguardStateController;
+    @Mock private SysuiStatusBarStateController mStatusBarStateController;
+    @Mock private ActivityStarter mActivityStarter;
 
     private int mCurrentUserId = 0;
     private StatusBarRemoteInputCallback mRemoteInputCallback;
@@ -71,7 +71,9 @@
         mContext.putComponent(CommandQueue.class, mock(CommandQueue.class));
 
         mRemoteInputCallback = spy(new StatusBarRemoteInputCallback(mContext,
-                mock(NotificationGroupManager.class)));
+                mock(NotificationGroupManager.class), mNotificationLockscreenUserManager,
+                mKeyguardStateController, mStatusBarStateController, mActivityStarter,
+                mShadeController));
         mRemoteInputCallback.mChallengeReceiver = mRemoteInputCallback.new ChallengeReceiver();
     }
 
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 f163886..f76dc61 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
@@ -65,7 +65,7 @@
 
 import androidx.test.filters.SmallTest;
 
-import com.android.internal.logging.MetricsLogger;
+import com.android.internal.colorextraction.ColorExtractor;
 import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
 import com.android.internal.logging.testing.FakeMetricsLogger;
 import com.android.internal.statusbar.IStatusBarService;
@@ -89,7 +89,6 @@
 import com.android.systemui.keyguard.ScreenLifecycle;
 import com.android.systemui.keyguard.WakefulnessLifecycle;
 import com.android.systemui.plugins.ActivityStarter.OnDismissAction;
-import com.android.systemui.plugins.FalsingManager;
 import com.android.systemui.plugins.statusbar.StatusBarStateController;
 import com.android.systemui.statusbar.CommandQueue;
 import com.android.systemui.statusbar.KeyguardIndicationController;
@@ -100,14 +99,15 @@
 import com.android.systemui.statusbar.NotificationMediaManager;
 import com.android.systemui.statusbar.NotificationPresenter;
 import com.android.systemui.statusbar.NotificationRemoteInputManager;
-import com.android.systemui.statusbar.NotificationShelf;
 import com.android.systemui.statusbar.NotificationViewHierarchyManager;
 import com.android.systemui.statusbar.PulseExpansionHandler;
 import com.android.systemui.statusbar.RemoteInputController;
 import com.android.systemui.statusbar.StatusBarState;
 import com.android.systemui.statusbar.StatusBarStateControllerImpl;
-import com.android.systemui.statusbar.SysuiStatusBarStateController;
+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.NotificationAlertingManager;
 import com.android.systemui.statusbar.notification.NotificationEntryListener;
 import com.android.systemui.statusbar.notification.NotificationEntryManager;
@@ -117,15 +117,20 @@
 import com.android.systemui.statusbar.notification.VisualStabilityManager;
 import com.android.systemui.statusbar.notification.collection.NotificationData;
 import com.android.systemui.statusbar.notification.collection.NotificationEntry;
+import com.android.systemui.statusbar.notification.logging.NotifLog;
 import com.android.systemui.statusbar.notification.logging.NotificationLogger;
 import com.android.systemui.statusbar.notification.row.NotificationGutsManager;
 import com.android.systemui.statusbar.notification.stack.NotificationListContainer;
 import com.android.systemui.statusbar.notification.stack.NotificationStackScrollLayout;
 import com.android.systemui.statusbar.policy.BatteryController;
+import com.android.systemui.statusbar.policy.ConfigurationController;
 import com.android.systemui.statusbar.policy.DeviceProvisionedController;
 import com.android.systemui.statusbar.policy.KeyguardStateController;
+import com.android.systemui.statusbar.policy.NetworkController;
 import com.android.systemui.statusbar.policy.RemoteInputQuickSettingsDisabler;
 import com.android.systemui.statusbar.policy.UserSwitcherController;
+import com.android.systemui.statusbar.policy.ZenModeController;
+import com.android.systemui.util.InjectionInflationController;
 
 import org.junit.Before;
 import org.junit.Test;
@@ -144,6 +149,15 @@
 @RunWith(AndroidTestingRunner.class)
 @RunWithLooper(setAsMainLooper = true)
 public class StatusBarTest extends SysuiTestCase {
+
+    private StatusBar mStatusBar;
+    private FakeMetricsLogger mMetricsLogger;
+    private PowerManager mPowerManager;
+    private TestableNotificationInterruptionStateProvider mNotificationInterruptionStateProvider;
+    private CommandQueue mCommandQueue;
+
+    @Mock private LightBarController mLightBarController;
+    @Mock private StatusBarIconController mStatusBarIconController;
     @Mock private StatusBarKeyguardViewManager mStatusBarKeyguardViewManager;
     @Mock private KeyguardStateController mKeyguardStateController;
     @Mock private KeyguardIndicationController mKeyguardIndicationController;
@@ -158,7 +172,6 @@
     @Mock private BiometricUnlockController mBiometricUnlockController;
     @Mock private NotificationData mNotificationData;
     @Mock private NotificationInterruptionStateProvider.HeadsUpSuppressor mHeadsUpSuppressor;
-    @Mock private NotificationViewHierarchyManager mViewHierarchyManager;
     @Mock private VisualStabilityManager mVisualStabilityManager;
     @Mock private NotificationListener mNotificationListener;
     @Mock private KeyguardViewMediator mKeyguardViewMediator;
@@ -185,17 +198,28 @@
     @Mock private NavigationBarController mNavigationBarController;
     @Mock private BypassHeadsUpNotifier mBypassHeadsUpNotifier;
     @Mock private SysuiColorExtractor mColorExtractor;
+    @Mock private ColorExtractor.GradientColors mGradientColors;
     @Mock private DozeLog mDozeLog;
     @Mock private PulseExpansionHandler mPulseExpansionHandler;
-    @Mock private RemoteInputQuickSettingsDisabler mRemoteInputQuickSettingsDisabler;
     @Mock private NotificationWakeUpCoordinator mNotificationWakeUpCoordinator;
     @Mock private KeyguardBypassController mKeyguardBypassController;
-
-    private TestableStatusBar mStatusBar;
-    private FakeMetricsLogger mMetricsLogger;
-    private PowerManager mPowerManager;
-    private TestableNotificationInterruptionStateProvider mNotificationInterruptionStateProvider;
-    private CommandQueue mCommandQueue;
+    @Mock private InjectionInflationController mInjectionInflationController;
+    @Mock private DynamicPrivacyController mDynamicPrivacyController;
+    @Mock private NotifPipelineInitializer mNotifPipelineInitializer;
+    @Mock private ZenModeController mZenModeController;
+    @Mock private AutoHideController mAutoHideController;
+    @Mock private NotificationViewHierarchyManager mNotificationViewHierarchyManager;
+    @Mock private UserSwitcherController mUserSwitcherController;
+    @Mock private NetworkController mNetworkController;
+    @Mock private VibratorHelper mVibratorHelper;
+    @Mock private BubbleController mBubbleController;
+    @Mock private NotificationGroupManager mGroupManager;
+    @Mock private NotificationGroupAlertTransferHelper mGroupAlertTransferHelper;
+    @Mock private StatusBarWindowController mStatusBarWindowController;
+    @Mock private NotificationIconAreaController mNotificationIconAreaController;
+    @Mock private StatusBarWindowViewController.Builder mStatusBarWindowViewControllerBuilder;
+    @Mock private StatusBarWindowViewController mStatusBarWindowViewController;
+    @Mock private NotifLog mNotifLog;
 
     @Before
     public void setup() throws Exception {
@@ -216,7 +240,7 @@
 
         mMetricsLogger = new FakeMetricsLogger();
         TestableNotificationEntryManager entryManager = new TestableNotificationEntryManager(
-                mContext);
+                mNotificationData);
         NotificationLogger notificationLogger = new NotificationLogger(mNotificationListener,
                 Dependency.get(UiOffloadThread.class), entryManager, mStatusBarStateController,
                 mExpansionStateLogger);
@@ -249,69 +273,98 @@
                 mHeadsUpManager, mHeadsUpSuppressor);
 
         when(mRemoteInputManager.getController()).thenReturn(mRemoteInputController);
-        mStatusBar = new TestableStatusBar(
-                mStatusBarKeyguardViewManager,
-                mKeyguardIndicationController,
-                mStackScroller,
-                mPowerManager,
-                mNotificationPanelView,
-                mBarService,
-                mNotificationListener,
-                notificationLogger,
-                mVisualStabilityManager,
-                mViewHierarchyManager,
-                entryManager,
-                mScrimController,
-                mBiometricUnlockController,
-                mKeyguardViewMediator,
-                mRemoteInputManager,
-                mock(NotificationGroupManager.class),
-                mock(NotificationGroupAlertTransferHelper.class),
-                new FalsingManagerFake(),
-                mock(StatusBarWindowController.class),
-                mock(NotificationIconAreaController.class),
-                mDozeScrimController,
-                mock(NotificationShelf.class),
-                mLockscreenUserManager,
-                mCommandQueue,
-                mNotificationPresenter,
-                mock(BubbleController.class),
-                mNavigationBarController,
-                mock(AutoHideController.class),
+
+        WakefulnessLifecycle wakefulnessLifecycle = new WakefulnessLifecycle();
+        wakefulnessLifecycle.dispatchStartedWakingUp();
+        wakefulnessLifecycle.dispatchFinishedWakingUp();
+
+        when(mGradientColors.supportsDarkText()).thenReturn(true);
+        when(mColorExtractor.getNeutralColors()).thenReturn(mGradientColors);
+        ConfigurationController configurationController = new ConfigurationControllerImpl(mContext);
+
+        when(mStatusBarWindowViewControllerBuilder.build())
+                .thenReturn(mStatusBarWindowViewController);
+
+        mStatusBar = new StatusBar(
+                mContext,
+                mLightBarController,
+                mAutoHideController,
                 mKeyguardUpdateMonitor,
-                mStatusBarWindowView,
-                mBroadcastDispatcher,
-                mAssistManager,
-                mNotificationGutsManager,
-                mNotificationMediaManager,
-                mForegroundServiceController,
-                mAppOpsController,
-                mStatusBarStateController,
-                mDeviceProvisionedController,
-                mNotificationAlertingManager,
-                mNotificationInterruptionStateProvider,
-                mMetricsLogger,
-                mHeadsUpManager,
-                mKeyguardStateController,
-                new ScreenLifecycle(),
-                mBypassHeadsUpNotifier,
-                mColorExtractor,
-                new DisplayMetrics(),
-                Dependency.get(UiOffloadThread.class),
+                mStatusBarIconController,
                 mDozeLog,
+                mInjectionInflationController,
                 mPulseExpansionHandler,
+                mNotificationWakeUpCoordinator,
+                mKeyguardBypassController,
+                mKeyguardStateController,
+                mHeadsUpManager,
+                mDynamicPrivacyController,
+                mBypassHeadsUpNotifier,
+                true,
+                mNotifPipelineInitializer,
+                new FalsingManagerFake(),
+                mBroadcastDispatcher,
                 new RemoteInputQuickSettingsDisabler(
                         mContext,
-                        new ConfigurationControllerImpl(mContext)
+                        configurationController
                 ),
-                mNotificationWakeUpCoordinator,
-                mKeyguardBypassController);
-        mStatusBar.mContext = mContext;
+                mNotificationGutsManager,
+                notificationLogger,
+                entryManager,
+                mNotificationInterruptionStateProvider,
+                mNotificationViewHierarchyManager,
+                mForegroundServiceController,
+                mAppOpsController,
+                mKeyguardViewMediator,
+                mZenModeController,
+                mNotificationAlertingManager,
+                new DisplayMetrics(),
+                mMetricsLogger,
+                Dependency.get(UiOffloadThread.class),
+                mNotificationMediaManager,
+                mLockscreenUserManager,
+                mRemoteInputManager,
+                mUserSwitcherController,
+                mNetworkController,
+                mBatteryController,
+                mColorExtractor,
+                new ScreenLifecycle(),
+                wakefulnessLifecycle,
+                mStatusBarStateController,
+                mVibratorHelper,
+                mBubbleController,
+                mGroupManager,
+                mGroupAlertTransferHelper,
+                mVisualStabilityManager,
+                mDeviceProvisionedController,
+                mNavigationBarController,
+                mAssistManager,
+                mNotificationListener,
+                configurationController,
+                mStatusBarWindowController,
+                mStatusBarWindowViewControllerBuilder,
+                mNotifLog);
+        // TODO: we should be able to call mStatusBar.start() and have all the below values
+        // initialized automatically.
         mStatusBar.mComponents = mContext.getComponents();
+        mStatusBar.mStatusBarKeyguardViewManager = mStatusBarKeyguardViewManager;
+        mStatusBar.mStatusBarWindow = mStatusBarWindowView;
+        mStatusBar.mBiometricUnlockController = mBiometricUnlockController;
+        mStatusBar.mScrimController = mScrimController;
+        mStatusBar.mNotificationPanel = mNotificationPanelView;
+        mStatusBar.mCommandQueue = mCommandQueue;
+        mStatusBar.mDozeScrimController = mDozeScrimController;
+        mStatusBar.mNotificationIconAreaController = mNotificationIconAreaController;
+        mStatusBar.mPresenter = mNotificationPresenter;
+        mStatusBar.mKeyguardIndicationController = mKeyguardIndicationController;
+        mStatusBar.mPowerManager = mPowerManager;
+        mStatusBar.mBarService = mBarService;
+        mStatusBar.mStackScroller = mStackScroller;
+        mStatusBar.mStatusBarWindowViewController = mStatusBarWindowViewController;
         mStatusBar.putComponent(StatusBar.class, mStatusBar);
         Dependency.get(InitController.class).executePostInitTasks();
         entryManager.setUpForTest(mock(NotificationPresenter.class), mStackScroller,
-                mHeadsUpManager, mNotificationData);
+                mHeadsUpManager);
         entryManager.addNotificationEntryListener(mEntryListener);
         notificationLogger.setUpWithContainer(mStackScroller);
     }
@@ -636,8 +689,8 @@
     @Test
     @RunWithLooper(setAsMainLooper = true)
     public void testUpdateKeyguardState_DoesNotCrash() {
-        mStatusBar.mState = StatusBarState.KEYGUARD;
-        when(mStatusBar.mLockscreenUserManager.getCurrentProfiles()).thenReturn(
+        mStatusBar.setBarStateForTest(StatusBarState.KEYGUARD);
+        when(mLockscreenUserManager.getCurrentProfiles()).thenReturn(
                 new SparseArray<>());
         mStatusBar.onStateChanged(StatusBarState.SHADE);
     }
@@ -741,11 +794,11 @@
         // Starting a pulse while docking should suppress wakeup gesture
         mStatusBar.mDozeServiceHost.pulseWhileDozing(mock(DozeHost.PulseCallback.class),
                 DozeEvent.PULSE_REASON_DOCKING);
-        verify(mStatusBarWindowView).suppressWakeUpGesture(eq(true));
+        verify(mStatusBarWindowViewController).suppressWakeUpGesture(eq(true));
 
         // Ending a pulse should restore wakeup gesture
         pulseCallback[0].onPulseFinished();
-        verify(mStatusBarWindowView).suppressWakeUpGesture(eq(false));
+        verify(mStatusBarWindowViewController).suppressWakeUpGesture(eq(false));
     }
 
     @Test
@@ -768,8 +821,7 @@
         verify(mStatusBarStateController).setState(eq(StatusBarState.KEYGUARD));
 
         // If useFullscreenUserSwitcher is true, state is set to FULLSCREEN_USER_SWITCHER.
-        mStatusBar.mUserSwitcherController = mock(UserSwitcherController.class);
-        when(mStatusBar.mUserSwitcherController.useFullscreenUserSwitcher()).thenReturn(true);
+        when(mUserSwitcherController.useFullscreenUserSwitcher()).thenReturn(true);
         mStatusBar.showKeyguardImpl();
         verify(mStatusBarStateController).setState(eq(StatusBarState.FULLSCREEN_USER_SWITCHER));
     }
@@ -821,155 +873,23 @@
                 any(UserHandle.class));
     }
 
-    static class TestableStatusBar extends StatusBar {
-        public TestableStatusBar(StatusBarKeyguardViewManager man,
-                KeyguardIndicationController key,
-                NotificationStackScrollLayout stack,
-                PowerManager pm, NotificationPanelView panelView,
-                IStatusBarService barService, NotificationListener notificationListener,
-                NotificationLogger notificationLogger,
-                VisualStabilityManager visualStabilityManager,
-                NotificationViewHierarchyManager viewHierarchyManager,
-                TestableNotificationEntryManager entryManager, ScrimController scrimController,
-                BiometricUnlockController biometricUnlockController,
-                KeyguardViewMediator keyguardViewMediator,
-                NotificationRemoteInputManager notificationRemoteInputManager,
-                NotificationGroupManager notificationGroupManager,
-                NotificationGroupAlertTransferHelper notificationGroupAlertTransferHelper,
-                FalsingManager falsingManager,
-                StatusBarWindowController statusBarWindowController,
-                NotificationIconAreaController notificationIconAreaController,
-                DozeScrimController dozeScrimController,
-                NotificationShelf notificationShelf,
-                NotificationLockscreenUserManager notificationLockscreenUserManager,
-                CommandQueue commandQueue,
-                StatusBarNotificationPresenter notificationPresenter,
-                BubbleController bubbleController,
-                NavigationBarController navBarController,
-                AutoHideController autoHideController,
-                KeyguardUpdateMonitor keyguardUpdateMonitor,
-                StatusBarWindowView statusBarWindow,
-                BroadcastDispatcher broadcastDispatcher,
-                AssistManager assistManager,
-                NotificationGutsManager notificationGutsManager,
-                NotificationMediaManager notificationMediaManager,
-                ForegroundServiceController foregroundServiceController,
-                AppOpsController appOpsController,
-                SysuiStatusBarStateController statusBarStateController,
-                DeviceProvisionedController deviceProvisionedController,
-                NotificationAlertingManager notificationAlertingManager,
-                NotificationInterruptionStateProvider notificationInterruptionStateProvider,
-                MetricsLogger metricsLogger,
-                HeadsUpManagerPhone headsUpManager,
-                KeyguardStateController keyguardStateController,
-                ScreenLifecycle screenLifecycle,
-                BypassHeadsUpNotifier bypassHeadsUpNotifier,
-                SysuiColorExtractor colorExtractor, DisplayMetrics displayMetrics,
-                UiOffloadThread uiOffloadThread,
-                DozeLog dozeLog,
-                PulseExpansionHandler pulseExpansionHandler,
-                RemoteInputQuickSettingsDisabler remoteInputQuickSettingsDisabler,
-                NotificationWakeUpCoordinator notificationWakeUpCoordinator,
-                KeyguardBypassController keyguardBypassController) {
-            mStatusBarKeyguardViewManager = man;
-            mKeyguardIndicationController = key;
-            mStackScroller = stack;
-            mPowerManager = pm;
-            mNotificationPanel = panelView;
-            mBarService = barService;
-            mNotificationListener = notificationListener;
-            mNotificationLogger = notificationLogger;
-            mWakefulnessLifecycle = createAwakeWakefulnessLifecycle();
-            mVisualStabilityManager = visualStabilityManager;
-            mViewHierarchyManager = viewHierarchyManager;
-            mEntryManager = entryManager;
-            mScrimController = scrimController;
-            mBiometricUnlockController = biometricUnlockController;
-            mKeyguardViewMediator = keyguardViewMediator;
-            mRemoteInputManager = notificationRemoteInputManager;
-            mGroupManager = notificationGroupManager;
-            mGroupAlertTransferHelper = notificationGroupAlertTransferHelper;
-            mFalsingManager = falsingManager;
-            mStatusBarWindowController = statusBarWindowController;
-            mNotificationIconAreaController = notificationIconAreaController;
-            mDozeScrimController = dozeScrimController;
-            mNotificationShelf = notificationShelf;
-            mLockscreenUserManager = notificationLockscreenUserManager;
-            mCommandQueue = commandQueue;
-            mPresenter = notificationPresenter;
-            mGestureWakeLock = mock(PowerManager.WakeLock.class);
-            mBubbleController = bubbleController;
-            mNavigationBarController = navBarController;
-            mAutoHideController = autoHideController;
-            mKeyguardUpdateMonitor = keyguardUpdateMonitor;
-            mStatusBarWindow = statusBarWindow;
-            mDozeServiceHost.mWakeLockScreenPerformsAuth = false;
-            mBroadcastDispatcher = broadcastDispatcher;
-            mAssistManager = assistManager;
-            mGutsManager = notificationGutsManager;
-            mMediaManager = notificationMediaManager;
-            mForegroundServiceController = foregroundServiceController;
-            mAppOpsController = appOpsController;
-            mStatusBarStateController = statusBarStateController;
-            mDeviceProvisionedController = deviceProvisionedController;
-            mNotificationAlertingManager = notificationAlertingManager;
-            mNotificationInterruptionStateProvider = notificationInterruptionStateProvider;
-            mMetricsLogger = metricsLogger;
-            mHeadsUpManager = headsUpManager;
-            mKeyguardStateController = keyguardStateController;
-            mScreenLifecycle = screenLifecycle;
-            mBypassHeadsUpNotifier = bypassHeadsUpNotifier;
-            mColorExtractor = colorExtractor;
-            mDisplayMetrics = displayMetrics;
-            mUiOffloadThread = uiOffloadThread;
-            mDozeLog = dozeLog;
-            mPulseExpansionHandler = pulseExpansionHandler;
-            mRemoteInputQuickSettingsDisabler = remoteInputQuickSettingsDisabler;
-            mWakeUpCoordinator = notificationWakeUpCoordinator;
-            mKeyguardBypassController = keyguardBypassController;
-        }
-
-        private WakefulnessLifecycle createAwakeWakefulnessLifecycle() {
-            WakefulnessLifecycle wakefulnessLifecycle = new WakefulnessLifecycle();
-            wakefulnessLifecycle.dispatchStartedWakingUp();
-            wakefulnessLifecycle.dispatchFinishedWakingUp();
-            return wakefulnessLifecycle;
-        }
-
-        @Override
-        protected void updateTheme() {
-            // Do nothing for now, until we have more mocking and StatusBar is smaller.
-        }
-
-        public void setBarStateForTest(int state) {
-            mState = state;
-        }
-
-        public void setUserSetupForTest(boolean userSetup) {
-            mUserSetup = userSetup;
-        }
-
-    }
-
     public static class TestableNotificationEntryManager extends NotificationEntryManager {
 
-        public TestableNotificationEntryManager(Context context) {
-            super(context);
+        public TestableNotificationEntryManager(NotificationData notificationData) {
+            super(notificationData, mock(NotifLog.class));
         }
 
         public void setUpForTest(NotificationPresenter presenter,
                 NotificationListContainer listContainer,
-                HeadsUpManagerPhone headsUpManager,
-                NotificationData notificationData) {
+                HeadsUpManagerPhone headsUpManager) {
             super.setUpWithPresenter(presenter, listContainer, headsUpManager);
-            mNotificationData = notificationData;
         }
     }
 
     public static class TestableNotificationInterruptionStateProvider extends
             NotificationInterruptionStateProvider {
 
-        public TestableNotificationInterruptionStateProvider(
+        TestableNotificationInterruptionStateProvider(
                 Context context,
                 PowerManager powerManager,
                 IDreamManager dreamManager,
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 00d87c3..0ef1acc 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
@@ -16,55 +16,95 @@
 
 package com.android.systemui.statusbar.phone;
 
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.spy;
 import static org.mockito.Mockito.verify;
 import static org.mockito.Mockito.when;
 
 import android.os.SystemClock;
+import android.testing.AndroidTestingRunner;
 import android.testing.TestableLooper;
 import android.view.MotionEvent;
 
 import androidx.test.filters.SmallTest;
-import androidx.test.runner.AndroidJUnit4;
 
-import com.android.systemui.Dependency;
+import com.android.systemui.SystemUIFactory;
 import com.android.systemui.SysuiTestCase;
-import com.android.systemui.plugins.statusbar.StatusBarStateController;
+import com.android.systemui.classifier.FalsingManagerFake;
+import com.android.systemui.doze.DozeLog;
+import com.android.systemui.shared.plugins.PluginManager;
 import com.android.systemui.statusbar.DragDownHelper;
-import com.android.systemui.statusbar.StatusBarState;
-import com.android.systemui.statusbar.notification.stack.NotificationStackScrollLayout;
+import com.android.systemui.statusbar.NotificationLockscreenUserManager;
+import com.android.systemui.statusbar.PulseExpansionHandler;
+import com.android.systemui.statusbar.SysuiStatusBarStateController;
+import com.android.systemui.statusbar.notification.DynamicPrivacyController;
+import com.android.systemui.statusbar.notification.NotificationEntryManager;
+import com.android.systemui.statusbar.notification.NotificationWakeUpCoordinator;
+import com.android.systemui.statusbar.policy.KeyguardStateController;
+import com.android.systemui.tuner.TunerService;
+import com.android.systemui.util.InjectionInflationController;
 
 import org.junit.Before;
 import org.junit.Test;
 import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
 
-@RunWith(AndroidJUnit4.class)
-@TestableLooper.RunWithLooper
+@RunWith(AndroidTestingRunner.class)
+@TestableLooper.RunWithLooper(setAsMainLooper = true)
 @SmallTest
 public class StatusBarWindowViewTest extends SysuiTestCase {
 
     private StatusBarWindowView mView;
-    private StatusBar mStatusBar;
-    private DragDownHelper mDragDownHelper;
-    private NotificationStackScrollLayout mStackScrollLayout;
+    private StatusBarWindowViewController mController;
+
+    @Mock private NotificationWakeUpCoordinator mCoordinator;
+    @Mock private PulseExpansionHandler mPulseExpansionHandler;
+    @Mock private DynamicPrivacyController mDynamicPrivacyController;
+    @Mock private KeyguardBypassController mBypassController;
+    @Mock private PluginManager mPluginManager;
+    @Mock private TunerService mTunerService;
+    @Mock private DragDownHelper mDragDownHelper;
+    @Mock private KeyguardStateController mKeyguardStateController;
+    @Mock private SysuiStatusBarStateController mStatusBarStateController;
+    @Mock private ShadeController mShadeController;
+    @Mock private NotificationLockscreenUserManager mNotificationLockScreenUserManager;
+    @Mock private NotificationEntryManager mNotificationEntryManager;
+    @Mock private StatusBar mStatusBar;
+    @Mock private DozeLog mDozeLog;
 
     @Before
     public void setUp() {
-        mDependency.injectMockDependency(StatusBarStateController.class);
-        mView = spy(new StatusBarWindowView(getContext(), null));
-        mStackScrollLayout = mock(NotificationStackScrollLayout.class);
-        when(mView.getStackScrollLayout()).thenReturn(mStackScrollLayout);
-        mStatusBar = mock(StatusBar.class);
-        mView.setService(mStatusBar);
-        mDragDownHelper = mock(DragDownHelper.class);
-        mView.setDragDownHelper(mDragDownHelper);
+        MockitoAnnotations.initMocks(this);
+
+        mView = new StatusBarWindowView(getContext(), null);
+        mContext.putComponent(StatusBar.class, mStatusBar);
+        when(mStatusBar.isDozing()).thenReturn(false);
+        mDependency.injectTestDependency(ShadeController.class, mShadeController);
+
+        mController = new StatusBarWindowViewController.Builder(
+                new InjectionInflationController(
+                        SystemUIFactory.getInstance().getRootComponent()),
+                mCoordinator,
+                mPulseExpansionHandler,
+                mDynamicPrivacyController,
+                mBypassController,
+                new FalsingManagerFake(),
+                mPluginManager,
+                mTunerService,
+                mNotificationLockScreenUserManager,
+                mNotificationEntryManager,
+                mKeyguardStateController,
+                mStatusBarStateController,
+                mDozeLog)
+                .setShadeController(mShadeController)
+                .setStatusBarWindowView(mView)
+                .build();
+        mController.setService(mStatusBar);
+        mController.setDragDownHelper(mDragDownHelper);
+
     }
 
     @Test
-    public void testDragDownHelperCalledWhenDraggingDown() throws Exception {
-        when(Dependency.get(StatusBarStateController.class).getState())
-                .thenReturn(StatusBarState.SHADE);
+    public void testDragDownHelperCalledWhenDraggingDown() {
         when(mDragDownHelper.isDraggingDown()).thenReturn(true);
         long now = SystemClock.elapsedRealtime();
         MotionEvent ev = MotionEvent.obtain(now, now, MotionEvent.ACTION_UP, 0 /* x */, 0 /* y */,
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/KeyButtonViewTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/KeyButtonViewTest.java
index d16dc16..943674a 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/KeyButtonViewTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/KeyButtonViewTest.java
@@ -40,6 +40,7 @@
 import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
 import com.android.systemui.SysuiTestCase;
 import com.android.systemui.bubbles.BubbleController;
+import com.android.systemui.recents.OverviewProxyService;
 
 import org.junit.Before;
 import org.junit.Test;
@@ -68,6 +69,7 @@
         MockitoAnnotations.initMocks(this);
         mMetricsLogger = mDependency.injectMockDependency(MetricsLogger.class);
         mBubbleController = mDependency.injectMockDependency(BubbleController.class);
+        mDependency.injectMockDependency(OverviewProxyService.class);
         TestableLooper.get(this).runWithLooper(() -> {
             mKeyButtonView = new KeyButtonView(mContext, null, 0, mInputManager);
         });
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/KeyguardStateControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/KeyguardStateControllerTest.java
new file mode 100644
index 0000000..e57bbc1
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/KeyguardStateControllerTest.java
@@ -0,0 +1,146 @@
+/*
+ * 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.policy;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.anyInt;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+import android.testing.AndroidTestingRunner;
+import android.testing.TestableLooper;
+
+import androidx.test.filters.SmallTest;
+
+import com.android.internal.widget.LockPatternUtils;
+import com.android.keyguard.KeyguardUpdateMonitor;
+import com.android.systemui.SysuiTestCase;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+
+@SmallTest
+@TestableLooper.RunWithLooper
+@RunWith(AndroidTestingRunner.class)
+public class KeyguardStateControllerTest extends SysuiTestCase {
+
+    @Mock
+    private KeyguardUpdateMonitor mKeyguardUpdateMonitor;
+    @Mock
+    private LockPatternUtils mLockPatternUtils;
+    private KeyguardStateController mKeyguardStateController;
+
+    @Before
+    public void setup() {
+        MockitoAnnotations.initMocks(this);
+        mKeyguardStateController = new KeyguardStateControllerImpl(mContext,
+                mKeyguardUpdateMonitor, mLockPatternUtils);
+    }
+
+    @Test
+    public void testAddCallback_registersListener() {
+        verify(mKeyguardUpdateMonitor).registerCallback(any());
+    }
+
+    @Test
+    public void testIsShowing() {
+        assertThat(mKeyguardStateController.isShowing()).isFalse();
+        mKeyguardStateController.notifyKeyguardState(true /* showing */, false /* occluded */);
+        assertThat(mKeyguardStateController.isShowing()).isTrue();
+    }
+
+    @Test
+    public void testIsMethodSecure() {
+        assertThat(mKeyguardStateController.isMethodSecure()).isFalse();
+
+        when(mLockPatternUtils.isSecure(anyInt())).thenReturn(true);
+        ((KeyguardStateControllerImpl) mKeyguardStateController).update(false /* alwaysUpdate */);
+        assertThat(mKeyguardStateController.isMethodSecure()).isTrue();
+    }
+
+    @Test
+    public void testIsOccluded() {
+        assertThat(mKeyguardStateController.isOccluded()).isFalse();
+        mKeyguardStateController.notifyKeyguardState(false /* showing */, true /* occluded */);
+        assertThat(mKeyguardStateController.isOccluded()).isTrue();
+    }
+
+    @Test
+    public void testCanSkipLockScreen() {
+        // Can skip because LockPatternUtils#isSecure is false
+        assertThat(mKeyguardStateController.canDismissLockScreen()).isTrue();
+
+        // Cannot skip after there's a password/pin/pattern
+        when(mLockPatternUtils.isSecure(anyInt())).thenReturn(true);
+        ((KeyguardStateControllerImpl) mKeyguardStateController).update(false /* alwaysUpdate */);
+        assertThat(mKeyguardStateController.canDismissLockScreen()).isFalse();
+
+        // Unless user is authenticated
+        when(mKeyguardUpdateMonitor.getUserCanSkipBouncer(anyInt())).thenReturn(true);
+        ((KeyguardStateControllerImpl) mKeyguardStateController).update(false /* alwaysUpdate */);
+        assertThat(mKeyguardStateController.canDismissLockScreen()).isTrue();
+    }
+
+    @Test
+    public void testIsUnlocked() {
+        // Is unlocked whenever the keyguard is not showing
+        assertThat(mKeyguardStateController.isShowing()).isFalse();
+        assertThat(mKeyguardStateController.isUnlocked()).isTrue();
+
+        // Unlocked if showing, but insecure
+        mKeyguardStateController.notifyKeyguardState(true /* showing */, false /* occluded */);
+        assertThat(mKeyguardStateController.isUnlocked()).isTrue();
+
+        // Locked if showing, and requires password
+        when(mLockPatternUtils.isSecure(anyInt())).thenReturn(true);
+        ((KeyguardStateControllerImpl) mKeyguardStateController).update(false /* alwaysUpdate */);
+        assertThat(mKeyguardStateController.isUnlocked()).isFalse();
+
+        // But unlocked after #getUserCanSkipBouncer allows it
+        when(mKeyguardUpdateMonitor.getUserCanSkipBouncer(anyInt())).thenReturn(true);
+        ((KeyguardStateControllerImpl) mKeyguardStateController).update(false /* alwaysUpdate */);
+        assertThat(mKeyguardStateController.isUnlocked()).isTrue();
+    }
+
+    @Test
+    public void testIsTrusted() {
+        assertThat(mKeyguardStateController.isTrusted()).isFalse();
+
+        when(mKeyguardUpdateMonitor.getUserHasTrust(anyInt())).thenReturn(true);
+        ((KeyguardStateControllerImpl) mKeyguardStateController).update(false /* alwaysUpdate */);
+
+        assertThat(mKeyguardStateController.isTrusted()).isTrue();
+    }
+
+    @Test
+    public void testCallbacksAreInvoked() {
+        KeyguardStateController.Callback callback = mock(KeyguardStateController.Callback.class);
+        mKeyguardStateController.addCallback(callback);
+
+        when(mKeyguardUpdateMonitor.getUserHasTrust(anyInt())).thenReturn(true);
+        ((KeyguardStateControllerImpl) mKeyguardStateController).update(false /* alwaysUpdate */);
+
+        verify(callback).onUnlockedChanged();
+    }
+
+}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/RemoteInputViewTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/RemoteInputViewTest.java
index bc468bf..390e812 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/RemoteInputViewTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/RemoteInputViewTest.java
@@ -106,7 +106,8 @@
 
     @Test
     public void testSendRemoteInput_intentContainsResultsAndSource() throws Exception {
-        ExpandableNotificationRow row = new NotificationTestHelper(mContext).createRow();
+        ExpandableNotificationRow row = new NotificationTestHelper(mContext, mDependency)
+                .createRow();
         RemoteInputView view = RemoteInputView.inflate(mContext, null, row.getEntry(), mController);
 
         setTestPendingIntent(view);
@@ -127,7 +128,7 @@
 
     private UserHandle getTargetInputMethodUser(UserHandle fromUser, UserHandle toUser)
             throws Exception {
-        ExpandableNotificationRow row = new NotificationTestHelper(mContext).createRow(
+        ExpandableNotificationRow row = new NotificationTestHelper(mContext, mDependency).createRow(
                 DUMMY_MESSAGE_APP_PKG,
                 UserHandle.getUid(fromUser.getIdentifier(), DUMMY_MESSAGE_APP_ID),
                 toUser);
@@ -169,7 +170,8 @@
 
     @Test
     public void testNoCrashWithoutVisibilityListener() throws Exception {
-        ExpandableNotificationRow row = new NotificationTestHelper(mContext).createRow();
+        ExpandableNotificationRow row = new NotificationTestHelper(mContext, mDependency)
+                .createRow();
         RemoteInputView view = RemoteInputView.inflate(mContext, null, row.getEntry(), mController);
 
         view.setOnVisibilityChangedListener(null);
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/SmartReplyViewTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/SmartReplyViewTest.java
index 0d56cbe..b5e4cb9 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/SmartReplyViewTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/SmartReplyViewTest.java
@@ -52,6 +52,7 @@
 import com.android.systemui.plugins.ActivityStarter;
 import com.android.systemui.plugins.ActivityStarter.OnDismissAction;
 import com.android.systemui.statusbar.NotificationEntryBuilder;
+import com.android.systemui.statusbar.NotificationRemoteInputManager;
 import com.android.systemui.statusbar.SmartReplyController;
 import com.android.systemui.statusbar.notification.collection.NotificationEntry;
 import com.android.systemui.statusbar.phone.KeyguardDismissUtil;
@@ -115,6 +116,7 @@
         });
         mDependency.injectMockDependency(KeyguardUpdateMonitor.class);
         mDependency.injectMockDependency(ShadeController.class);
+        mDependency.injectMockDependency(NotificationRemoteInputManager.class);
         mDependency.injectTestDependency(ActivityStarter.class, mActivityStarter);
         mDependency.injectTestDependency(SmartReplyConstants.class, mConstants);
 
diff --git a/services/accessibility/java/com/android/server/accessibility/AbstractAccessibilityServiceConnection.java b/services/accessibility/java/com/android/server/accessibility/AbstractAccessibilityServiceConnection.java
index 4f021ad..950fa8d 100644
--- a/services/accessibility/java/com/android/server/accessibility/AbstractAccessibilityServiceConnection.java
+++ b/services/accessibility/java/com/android/server/accessibility/AbstractAccessibilityServiceConnection.java
@@ -91,7 +91,7 @@
     protected final Context mContext;
     protected final SystemSupport mSystemSupport;
     protected final WindowManagerInternal mWindowManagerService;
-    private final GlobalActionPerformer mGlobalActionPerformer;
+    private final SystemActionPerformer mSystemActionPerformer;
     private final AccessibilityWindowManager mA11yWindowManager;
     private final DisplayManager mDisplayManager;
     private final PowerManager mPowerManager;
@@ -213,7 +213,7 @@
             AccessibilityServiceInfo accessibilityServiceInfo, int id, Handler mainHandler,
             Object lock, AccessibilitySecurityPolicy securityPolicy, SystemSupport systemSupport,
             WindowManagerInternal windowManagerInternal,
-            GlobalActionPerformer globalActionPerfomer,
+            SystemActionPerformer systemActionPerfomer,
             AccessibilityWindowManager a11yWindowManager) {
         mContext = context;
         mWindowManagerService = windowManagerInternal;
@@ -222,7 +222,7 @@
         mAccessibilityServiceInfo = accessibilityServiceInfo;
         mLock = lock;
         mSecurityPolicy = securityPolicy;
-        mGlobalActionPerformer = globalActionPerfomer;
+        mSystemActionPerformer = systemActionPerfomer;
         mSystemSupport = systemSupport;
         mInvocationHandler = new InvocationHandler(mainHandler.getLooper());
         mA11yWindowManager = a11yWindowManager;
@@ -350,9 +350,9 @@
 
     protected abstract boolean hasRightsToCurrentUserLocked();
 
+    @Nullable
     @Override
-    public List<AccessibilityWindowInfo> getWindows() {
-        ensureWindowsAvailableTimed(Display.DEFAULT_DISPLAY);
+    public AccessibilityWindowInfo.WindowListSparseArray getWindows() {
         synchronized (mLock) {
             if (!hasRightsToCurrentUserLocked()) {
                 return null;
@@ -362,38 +362,39 @@
             if (!permissionGranted) {
                 return null;
             }
-            List<AccessibilityWindowInfo> internalWindowList =
-                    mA11yWindowManager.getWindowListLocked(Display.DEFAULT_DISPLAY);
-            if (internalWindowList == null) {
-                return null;
-            }
             if (!mSecurityPolicy.checkAccessibilityAccess(this)) {
                 return null;
             }
-            List<AccessibilityWindowInfo> returnedWindowList = new ArrayList<>();
-            final int windowCount = internalWindowList.size();
-            for (int i = 0; i < windowCount; i++) {
-                AccessibilityWindowInfo window = internalWindowList.get(i);
-                AccessibilityWindowInfo windowClone =
-                        AccessibilityWindowInfo.obtain(window);
-                windowClone.setConnectionId(mId);
-                returnedWindowList.add(windowClone);
+            final AccessibilityWindowInfo.WindowListSparseArray allWindows =
+                    new AccessibilityWindowInfo.WindowListSparseArray();
+            final ArrayList<Integer> displayList = mA11yWindowManager.getDisplayListLocked();
+            final int displayListCounts = displayList.size();
+            if (displayListCounts > 0) {
+                for (int i = 0; i < displayListCounts; i++) {
+                    final int displayId = displayList.get(i);
+                    ensureWindowsAvailableTimedLocked(displayId);
+
+                    final List<AccessibilityWindowInfo> windowList = getWindowsByDisplayLocked(
+                            displayId);
+                    if (windowList != null) {
+                        allWindows.put(displayId, windowList);
+                    }
+                }
             }
-            return returnedWindowList;
+            return allWindows;
         }
     }
 
     @Override
     public AccessibilityWindowInfo getWindow(int windowId) {
-        int displayId = Display.INVALID_DISPLAY;
         synchronized (mLock) {
+            int displayId = Display.INVALID_DISPLAY;
             if (windowId != AccessibilityWindowInfo.UNDEFINED_WINDOW_ID) {
                 displayId = mA11yWindowManager.getDisplayIdByUserIdAndWindowIdLocked(
                         mSystemSupport.getCurrentUserIdLocked(), windowId);
             }
-        }
-        ensureWindowsAvailableTimed(displayId);
-        synchronized (mLock) {
+            ensureWindowsAvailableTimedLocked(displayId);
+
             if (!hasRightsToCurrentUserLocked()) {
                 return null;
             }
@@ -759,7 +760,7 @@
                 return false;
             }
         }
-        return mGlobalActionPerformer.performGlobalAction(action);
+        return mSystemActionPerformer.performSystemAction(action);
     }
 
     @Override
@@ -1316,35 +1317,33 @@
      *
      * @param displayId The logical display id.
      */
-    private void ensureWindowsAvailableTimed(int displayId) {
-        synchronized (mLock) {
-            if (mA11yWindowManager.getWindowListLocked(displayId) != null) {
-                return;
-            }
-            // If we have no registered callback, update the state we
-            // we may have to register one but it didn't happen yet.
-            if (!mA11yWindowManager.isTrackingWindowsLocked(displayId)) {
-                // Invokes client change to make sure tracking window enabled.
-                mSystemSupport.onClientChangeLocked(false);
-            }
-            // We have no windows but do not care about them, done.
-            if (!mA11yWindowManager.isTrackingWindowsLocked(displayId)) {
-                return;
-            }
+    private void ensureWindowsAvailableTimedLocked(int displayId) {
+        if (mA11yWindowManager.getWindowListLocked(displayId) != null) {
+            return;
+        }
+        // If we have no registered callback, update the state we
+        // we may have to register one but it didn't happen yet.
+        if (!mA11yWindowManager.isTrackingWindowsLocked(displayId)) {
+            // Invokes client change to make sure tracking window enabled.
+            mSystemSupport.onClientChangeLocked(false);
+        }
+        // We have no windows but do not care about them, done.
+        if (!mA11yWindowManager.isTrackingWindowsLocked(displayId)) {
+            return;
+        }
 
-            // Wait for the windows with a timeout.
-            final long startMillis = SystemClock.uptimeMillis();
-            while (mA11yWindowManager.getWindowListLocked(displayId) == null) {
-                final long elapsedMillis = SystemClock.uptimeMillis() - startMillis;
-                final long remainMillis = WAIT_WINDOWS_TIMEOUT_MILLIS - elapsedMillis;
-                if (remainMillis <= 0) {
-                    return;
-                }
-                try {
-                    mLock.wait(remainMillis);
-                } catch (InterruptedException ie) {
-                    /* ignore */
-                }
+        // Wait for the windows with a timeout.
+        final long startMillis = SystemClock.uptimeMillis();
+        while (mA11yWindowManager.getWindowListLocked(displayId) == null) {
+            final long elapsedMillis = SystemClock.uptimeMillis() - startMillis;
+            final long remainMillis = WAIT_WINDOWS_TIMEOUT_MILLIS - elapsedMillis;
+            if (remainMillis <= 0) {
+                return;
+            }
+            try {
+                mLock.wait(remainMillis);
+            } catch (InterruptedException ie) {
+                /* ignore */
             }
         }
     }
@@ -1442,6 +1441,24 @@
                 interrogatingPid, interrogatingTid);
     }
 
+    private List<AccessibilityWindowInfo> getWindowsByDisplayLocked(int displayId) {
+        final List<AccessibilityWindowInfo> internalWindowList =
+                mA11yWindowManager.getWindowListLocked(displayId);
+        if (internalWindowList == null) {
+            return null;
+        }
+        final List<AccessibilityWindowInfo> returnedWindowList = new ArrayList<>();
+        final int windowCount = internalWindowList.size();
+        for (int i = 0; i < windowCount; i++) {
+            AccessibilityWindowInfo window = internalWindowList.get(i);
+            AccessibilityWindowInfo windowClone =
+                    AccessibilityWindowInfo.obtain(window);
+            windowClone.setConnectionId(mId);
+            returnedWindowList.add(windowClone);
+        }
+        return returnedWindowList;
+    }
+
     public ComponentName getComponentName() {
         return mComponentName;
     }
diff --git a/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java b/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java
index 1f11059..91269c7 100644
--- a/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java
+++ b/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java
@@ -30,6 +30,7 @@
 import android.accessibilityservice.AccessibilityGestureEvent;
 import android.accessibilityservice.AccessibilityService;
 import android.accessibilityservice.AccessibilityServiceInfo;
+import android.accessibilityservice.AccessibilityShortcutInfo;
 import android.accessibilityservice.IAccessibilityServiceClient;
 import android.annotation.NonNull;
 import android.annotation.Nullable;
@@ -197,7 +198,7 @@
 
     private final MainHandler mMainHandler;
 
-    private final GlobalActionPerformer mGlobalActionPerformer;
+    private final SystemActionPerformer mSystemActionPerformer;
 
     private MagnificationController mMagnificationController;
 
@@ -271,7 +272,7 @@
         mWindowManagerService = LocalServices.getService(WindowManagerInternal.class);
         mSecurityPolicy = new AccessibilitySecurityPolicy(mContext, this);
         mMainHandler = new MainHandler(mContext.getMainLooper());
-        mGlobalActionPerformer = new GlobalActionPerformer(mContext, mWindowManagerService);
+        mSystemActionPerformer = new SystemActionPerformer(mContext, mWindowManagerService);
         mA11yWindowManager = new AccessibilityWindowManager(mLock, mMainHandler,
                 mWindowManagerService, this, mSecurityPolicy, this);
         mA11yDisplayListener = new AccessibilityDisplayListener(mContext, mMainHandler);
@@ -729,7 +730,7 @@
         synchronized (mLock) {
             mUiAutomationManager.registerUiTestAutomationServiceLocked(owner, serviceClient,
                     mContext, accessibilityServiceInfo, sIdCounter++, mMainHandler,
-                    mSecurityPolicy, this, mWindowManagerService, mGlobalActionPerformer,
+                    mSecurityPolicy, this, mWindowManagerService, mSystemActionPerformer,
                     mA11yWindowManager, flags);
             onUserStateChangedLocked(getCurrentUserStateLocked());
         }
@@ -1208,6 +1209,18 @@
         return false;
     }
 
+    private boolean readInstalledAccessibilityShortcutLocked(UserState userState) {
+        final List<AccessibilityShortcutInfo> shortcutInfos = AccessibilityManager
+                .getInstance(mContext).getInstalledAccessibilityShortcutListAsUser(
+                        mContext, mCurrentUserId);
+        if (!shortcutInfos.equals(userState.mInstalledShortcuts)) {
+            userState.mInstalledShortcuts.clear();
+            userState.mInstalledShortcuts.addAll(shortcutInfos);
+            return true;
+        }
+        return false;
+    }
+
     private boolean readEnabledAccessibilityServicesLocked(UserState userState) {
         mTempComponentNameSet.clear();
         readComponentNamesFromSettingLocked(Settings.Secure.ENABLED_ACCESSIBILITY_SERVICES,
@@ -1437,7 +1450,7 @@
                 if (service == null) {
                     service = new AccessibilityServiceConnection(userState, mContext, componentName,
                             installedService, sIdCounter++, mMainHandler, mLock, mSecurityPolicy,
-                            this, mWindowManagerService, mGlobalActionPerformer,
+                            this, mWindowManagerService, mSystemActionPerformer,
                             mA11yWindowManager);
                 } else if (userState.mBoundServices.contains(service)) {
                     continue;
@@ -1741,6 +1754,7 @@
 
     private boolean readConfigurationForUserStateLocked(UserState userState) {
         boolean somethingChanged = readInstalledAccessibilityServiceLocked(userState);
+        somethingChanged |= readInstalledAccessibilityShortcutLocked(userState);
         somethingChanged |= readEnabledAccessibilityServicesLocked(userState);
         somethingChanged |= readTouchExplorationGrantedAccessibilityServicesLocked(userState);
         somethingChanged |= readTouchExplorationEnabledSettingLocked(userState);
@@ -2468,7 +2482,7 @@
                     userState, mContext,
                     COMPONENT_NAME, info, sIdCounter++, mMainHandler, mLock, mSecurityPolicy,
                     AccessibilityManagerService.this, mWindowManagerService,
-                    mGlobalActionPerformer, mA11yWindowManager) {
+                    mSystemActionPerformer, mA11yWindowManager) {
                 @Override
                 public boolean supportsFlagForNotImportantViews(AccessibilityServiceInfo info) {
                     return true;
@@ -2671,6 +2685,8 @@
         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<>();
@@ -3083,6 +3099,8 @@
                         || mUserInteractiveUiTimeoutUri.equals(uri)) {
                     readUserRecommendedUiTimeoutSettingsLocked(userState);
                 }
+                // TODO(a11y shortcut): Monitor new setting keys, when user adds shortcut, and
+                //  remove from the list of enabled targets anything that's been uninstalled.
             }
         }
     }
diff --git a/services/accessibility/java/com/android/server/accessibility/AccessibilityServiceConnection.java b/services/accessibility/java/com/android/server/accessibility/AccessibilityServiceConnection.java
index d7f61e5..e7f3ccc 100644
--- a/services/accessibility/java/com/android/server/accessibility/AccessibilityServiceConnection.java
+++ b/services/accessibility/java/com/android/server/accessibility/AccessibilityServiceConnection.java
@@ -71,9 +71,9 @@
             AccessibilityServiceInfo accessibilityServiceInfo, int id, Handler mainHandler,
             Object lock, AccessibilitySecurityPolicy securityPolicy, SystemSupport systemSupport,
             WindowManagerInternal windowManagerInternal,
-            GlobalActionPerformer globalActionPerfomer, AccessibilityWindowManager awm) {
+            SystemActionPerformer systemActionPerfomer, AccessibilityWindowManager awm) {
         super(context, componentName, accessibilityServiceInfo, id, mainHandler, lock,
-                securityPolicy, systemSupport, windowManagerInternal, globalActionPerfomer, awm);
+                securityPolicy, systemSupport, windowManagerInternal, systemActionPerfomer, awm);
         mUserStateWeakReference = new WeakReference<UserState>(userState);
         mIntent = new Intent().setComponent(mComponentName);
         mMainHandler = mainHandler;
diff --git a/services/accessibility/java/com/android/server/accessibility/AccessibilityWindowManager.java b/services/accessibility/java/com/android/server/accessibility/AccessibilityWindowManager.java
index 0038a27..cb858ac 100644
--- a/services/accessibility/java/com/android/server/accessibility/AccessibilityWindowManager.java
+++ b/services/accessibility/java/com/android/server/accessibility/AccessibilityWindowManager.java
@@ -1472,11 +1472,27 @@
     public int getDisplayIdByUserIdAndWindowIdLocked(int userId, int windowId) {
         final IBinder windowToken = getWindowTokenForUserAndWindowIdLocked(userId, windowId);
         final int displayId = mWindowManagerInternal.getDisplayIdForWindow(windowToken);
-
         return displayId;
     }
 
     /**
+     * Returns the display list including all displays which are tracking windows.
+     *
+     * @return The display list.
+     */
+    public ArrayList<Integer> getDisplayListLocked() {
+        final ArrayList<Integer> displayList = new ArrayList<>();
+        final int count = mDisplayWindowsObservers.size();
+        for (int i = 0; i < count; i++) {
+            final DisplayWindowsObserver observer = mDisplayWindowsObservers.valueAt(i);
+            if (observer != null) {
+                displayList.add(observer.mDisplayId);
+            }
+        }
+        return displayList;
+    }
+
+    /**
      * Gets current input focused window token from window manager, and returns its windowId.
      *
      * @param userId The userId
diff --git a/services/accessibility/java/com/android/server/accessibility/GlobalActionPerformer.java b/services/accessibility/java/com/android/server/accessibility/SystemActionPerformer.java
similarity index 87%
rename from services/accessibility/java/com/android/server/accessibility/GlobalActionPerformer.java
rename to services/accessibility/java/com/android/server/accessibility/SystemActionPerformer.java
index b9b2654..19ac0d3 100644
--- a/services/accessibility/java/com/android/server/accessibility/GlobalActionPerformer.java
+++ b/services/accessibility/java/com/android/server/accessibility/SystemActionPerformer.java
@@ -1,17 +1,17 @@
 /*
- ** Copyright 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.
+ * 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.accessibility;
@@ -40,12 +40,12 @@
 /**
  * Handle the back-end of AccessibilityService#performGlobalAction
  */
-public class GlobalActionPerformer {
+public class SystemActionPerformer {
     private final WindowManagerInternal mWindowManagerService;
     private final Context mContext;
     private Supplier<ScreenshotHelper> mScreenshotHelperSupplier;
 
-    public GlobalActionPerformer(Context context, WindowManagerInternal windowManagerInternal) {
+    public SystemActionPerformer(Context context, WindowManagerInternal windowManagerInternal) {
         mContext = context;
         mWindowManagerService = windowManagerInternal;
         mScreenshotHelperSupplier = null;
@@ -53,13 +53,16 @@
 
     // Used to mock ScreenshotHelper
     @VisibleForTesting
-    public GlobalActionPerformer(Context context, WindowManagerInternal windowManagerInternal,
+    public SystemActionPerformer(Context context, WindowManagerInternal windowManagerInternal,
             Supplier<ScreenshotHelper> screenshotHelperSupplier) {
         this(context, windowManagerInternal);
         mScreenshotHelperSupplier = screenshotHelperSupplier;
     }
 
-    public boolean performGlobalAction(int action) {
+    /**
+     * Performe the system action matching the given action id.
+     */
+    public boolean performSystemAction(int action) {
         final long identity = Binder.clearCallingIdentity();
         try {
             switch (action) {
diff --git a/services/accessibility/java/com/android/server/accessibility/UiAutomationManager.java b/services/accessibility/java/com/android/server/accessibility/UiAutomationManager.java
index 79d975d..7dd4a70 100644
--- a/services/accessibility/java/com/android/server/accessibility/UiAutomationManager.java
+++ b/services/accessibility/java/com/android/server/accessibility/UiAutomationManager.java
@@ -87,7 +87,7 @@
             AccessibilitySecurityPolicy securityPolicy,
             AbstractAccessibilityServiceConnection.SystemSupport systemSupport,
             WindowManagerInternal windowManagerInternal,
-            GlobalActionPerformer globalActionPerfomer,
+            SystemActionPerformer systemActionPerfomer,
             AccessibilityWindowManager awm, int flags) {
         synchronized (mLock) {
             accessibilityServiceInfo.setComponentName(COMPONENT_NAME);
@@ -108,7 +108,7 @@
             mSystemSupport = systemSupport;
             mUiAutomationService = new UiAutomationService(context, accessibilityServiceInfo, id,
                     mainHandler, mLock, securityPolicy, systemSupport, windowManagerInternal,
-                    globalActionPerfomer, awm);
+                    systemActionPerfomer, awm);
             mUiAutomationServiceOwner = owner;
             mUiAutomationFlags = flags;
             mUiAutomationServiceInfo = accessibilityServiceInfo;
@@ -226,9 +226,9 @@
                 int id, Handler mainHandler, Object lock,
                 AccessibilitySecurityPolicy securityPolicy,
                 SystemSupport systemSupport, WindowManagerInternal windowManagerInternal,
-                GlobalActionPerformer globalActionPerfomer, AccessibilityWindowManager awm) {
+                SystemActionPerformer systemActionPerfomer, AccessibilityWindowManager awm) {
             super(context, COMPONENT_NAME, accessibilityServiceInfo, id, mainHandler, lock,
-                    securityPolicy, systemSupport, windowManagerInternal, globalActionPerfomer,
+                    securityPolicy, systemSupport, windowManagerInternal, systemActionPerfomer,
                     awm);
             mMainHandler = mainHandler;
         }
diff --git a/services/accessibility/java/com/android/server/accessibility/gestures/AccessibilityGestureDetector.java b/services/accessibility/java/com/android/server/accessibility/gestures/AccessibilityGestureDetector.java
index 7e8fb29..3dfe59e 100644
--- a/services/accessibility/java/com/android/server/accessibility/gestures/AccessibilityGestureDetector.java
+++ b/services/accessibility/java/com/android/server/accessibility/gestures/AccessibilityGestureDetector.java
@@ -408,9 +408,6 @@
         cancelGesture();
     }
 
-    public boolean firstTapDetected() {
-        return mFirstTapDetected;
-    }
 
     @Override
     public void onLongPress(MotionEvent e) {
diff --git a/services/accessibility/java/com/android/server/accessibility/gestures/TouchExplorer.java b/services/accessibility/java/com/android/server/accessibility/gestures/TouchExplorer.java
index c60e35e..b62e260 100644
--- a/services/accessibility/java/com/android/server/accessibility/gestures/TouchExplorer.java
+++ b/services/accessibility/java/com/android/server/accessibility/gestures/TouchExplorer.java
@@ -411,24 +411,12 @@
         // we resent the delayed callback and wait again.
         mSendHoverEnterAndMoveDelayed.cancel();
         mSendHoverExitDelayed.cancel();
-
         // If a touch exploration gesture is in progress send events for its end.
         if (mState.isTouchExploring()) {
             sendHoverExitAndTouchExplorationGestureEndIfNeeded(policyFlags);
         }
 
-        // Avoid duplicated TYPE_TOUCH_INTERACTION_START event when 2nd tap of double
-        // tap.
-        if (!mGestureDetector.firstTapDetected() && mState.isClear()) {
-            mSendTouchExplorationEndDelayed.forceSendAndRemove();
-            mSendTouchInteractionEndDelayed.forceSendAndRemove();
-            mDispatcher.sendAccessibilityEvent(AccessibilityEvent.TYPE_TOUCH_INTERACTION_START);
-        } else {
-            // Let gesture to handle to avoid duplicated TYPE_TOUCH_INTERACTION_END event.
-            mSendTouchInteractionEndDelayed.cancel();
-        }
-
-        if (!mGestureDetector.firstTapDetected() && !mState.isTouchExploring()) {
+        if (mState.isClear()) {
             if (!mSendHoverEnterAndMoveDelayed.isPending()) {
                 // Queue a delayed transition to STATE_TOUCH_EXPLORING.
                 // If we do not detect that this is a gesture, delegation or drag the transition
@@ -441,6 +429,12 @@
                 // Cache the event until we discern exploration from gesturing.
                 mSendHoverEnterAndMoveDelayed.addEvent(event, rawEvent);
             }
+            mSendTouchExplorationEndDelayed.forceSendAndRemove();
+            mSendTouchInteractionEndDelayed.forceSendAndRemove();
+            mDispatcher.sendAccessibilityEvent(AccessibilityEvent.TYPE_TOUCH_INTERACTION_START);
+        } else {
+            // Avoid duplicated TYPE_TOUCH_INTERACTION_START event when 2nd tap of double tap.
+            mSendTouchInteractionEndDelayed.cancel();
         }
     }
 
diff --git a/services/core/Android.bp b/services/core/Android.bp
index 6a3b38e..4f4e47a 100644
--- a/services/core/Android.bp
+++ b/services/core/Android.bp
@@ -48,7 +48,7 @@
         ":services.core.protolog.json",
     ],
     cmd: "cp $(location :generate-protolog.json) $(out) && " +
-      "{ diff $(out) $(location :services.core.protolog.json) >/dev/null 2>&1 || " +
+      "{ ! (diff $(out) $(location :services.core.protolog.json) | grep -q '^<') || " +
       "{ echo -e '\\n\\n################################################################\\n#\\n" +
       "#  ERROR: ProtoLog viewer config is stale.  To update it, run:\\n#\\n" +
       "#  cp $(location :generate-protolog.json) " +
@@ -108,7 +108,7 @@
         "android.hardware.biometrics.fingerprint-V2.1-java",
         "android.hardware.oemlock-V1.0-java",
         "android.hardware.tetheroffload.control-V1.0-java",
-        "android.hardware.vibrator-V1.0-java",
+        "android.hardware.vibrator-V1.4-java",
         "android.hardware.configstore-V1.0-java",
         "android.hardware.contexthub-V1.0-java",
         "android.hidl.manager-V1.2-java",
@@ -146,7 +146,8 @@
     name: "services.core.json.gz",
     srcs: [":checked-protolog.json"],
     out: ["services.core.protolog.json.gz"],
-    cmd: "gzip < $(in) > $(out)",
+    cmd: "$(location minigzip) -c < $(in) > $(out)",
+    tools: ["minigzip"],
 }
 
 prebuilt_etc {
diff --git a/core/java/android/content/pm/PackageManagerInternal.java b/services/core/java/android/content/pm/PackageManagerInternal.java
similarity index 99%
rename from core/java/android/content/pm/PackageManagerInternal.java
rename to services/core/java/android/content/pm/PackageManagerInternal.java
index 3eef92f..1d666ad 100644
--- a/core/java/android/content/pm/PackageManagerInternal.java
+++ b/services/core/java/android/content/pm/PackageManagerInternal.java
@@ -33,6 +33,8 @@
 import android.util.ArraySet;
 import android.util.SparseArray;
 
+import com.android.server.pm.PackageList;
+
 import java.io.IOException;
 import java.lang.annotation.Retention;
 import java.lang.annotation.RetentionPolicy;
diff --git a/services/core/java/com/android/server/ConnectivityService.java b/services/core/java/com/android/server/ConnectivityService.java
index 9acafae..e0f60b4 100644
--- a/services/core/java/com/android/server/ConnectivityService.java
+++ b/services/core/java/com/android/server/ConnectivityService.java
@@ -579,6 +579,8 @@
     // the set of network types that can only be enabled by system/sig apps
     private List mProtectedNetworks;
 
+    private Set<String> mWolSupportedInterfaces;
+
     private TelephonyManager mTelephonyManager;
 
     private KeepaliveTracker mKeepaliveTracker;
@@ -1055,6 +1057,10 @@
             }
         }
 
+        mWolSupportedInterfaces = new ArraySet(
+                mContext.getResources().getStringArray(
+                        com.android.internal.R.array.config_wakeonlan_supported_interfaces));
+
         mUserManager = (UserManager) context.getSystemService(Context.USER_SERVICE);
 
         mTethering = deps.makeTethering(mContext, mNMS, mStatsService, mPolicyManager,
@@ -3268,7 +3274,8 @@
         final NetworkRequestInfo nri = mNetworkRequests.get(request);
 
         if (nri != null) {
-            if (Process.SYSTEM_UID != callingUid && nri.mUid != callingUid) {
+            if (Process.SYSTEM_UID != callingUid && Process.NETWORK_STACK_UID != callingUid
+                    && nri.mUid != callingUid) {
                 log(String.format("UID %d attempted to %s for unowned request %s",
                         callingUid, requestedOperation, nri));
                 return null;
@@ -5599,6 +5606,9 @@
         } else {
             updateProxy(newLp, oldLp);
         }
+
+        updateWakeOnLan(newLp);
+
         // TODO - move this check to cover the whole function
         if (!Objects.equals(newLp, oldLp)) {
             synchronized (networkAgent) {
@@ -5769,6 +5779,10 @@
         }
     }
 
+    private void updateWakeOnLan(@NonNull LinkProperties lp) {
+        lp.setWakeOnLanSupported(mWolSupportedInterfaces.contains(lp.getInterfaceName()));
+    }
+
     private int getNetworkPermission(NetworkCapabilities nc) {
         if (!nc.hasCapability(NET_CAPABILITY_NOT_RESTRICTED)) {
             return INetd.PERMISSION_SYSTEM;
diff --git a/services/core/java/com/android/server/ContextHubSystemService.java b/services/core/java/com/android/server/ContextHubSystemService.java
index 110847d..c6853a5 100644
--- a/services/core/java/com/android/server/ContextHubSystemService.java
+++ b/services/core/java/com/android/server/ContextHubSystemService.java
@@ -16,12 +16,12 @@
 
 package com.android.server;
 
-import com.android.internal.util.ConcurrentUtils;
-import com.android.server.location.ContextHubService;
-import com.android.server.SystemServerInitThreadPool;
 import android.content.Context;
 import android.util.Log;
 
+import com.android.internal.util.ConcurrentUtils;
+import com.android.server.location.ContextHubService;
+
 import java.util.concurrent.Future;
 
 class ContextHubSystemService extends SystemService {
@@ -32,7 +32,7 @@
 
     public ContextHubSystemService(Context context) {
         super(context);
-        mInit = SystemServerInitThreadPool.get().submit(() -> {
+        mInit = SystemServerInitThreadPool.submit(() -> {
             mContextHubService = new ContextHubService(context);
         }, "Init ContextHubSystemService");
     }
diff --git a/services/core/java/com/android/server/LocationManagerService.java b/services/core/java/com/android/server/LocationManagerService.java
index 35a06a9..09f62ff 100644
--- a/services/core/java/com/android/server/LocationManagerService.java
+++ b/services/core/java/com/android/server/LocationManagerService.java
@@ -3064,11 +3064,6 @@
             try {
                 LocationProvider oldProvider = getLocationProviderLocked(name);
                 if (oldProvider != null) {
-                    if (oldProvider.isMock()) {
-                        throw new IllegalArgumentException(
-                                "Provider \"" + name + "\" already exists");
-                    }
-
                     removeProviderLocked(oldProvider);
                 }
 
@@ -3093,7 +3088,7 @@
             try {
                 LocationProvider testProvider = getLocationProviderLocked(name);
                 if (testProvider == null || !testProvider.isMock()) {
-                    throw new IllegalArgumentException("Provider \"" + name + "\" unknown");
+                    return;
                 }
 
                 removeProviderLocked(testProvider);
diff --git a/services/core/java/com/android/server/PersistentDataBlockService.java b/services/core/java/com/android/server/PersistentDataBlockService.java
index bd5ad96..73c8520 100644
--- a/services/core/java/com/android/server/PersistentDataBlockService.java
+++ b/services/core/java/com/android/server/PersistentDataBlockService.java
@@ -162,7 +162,7 @@
     @Override
     public void onStart() {
         // Do init on a separate thread, will join in PHASE_ACTIVITY_MANAGER_READY
-        SystemServerInitThreadPool.get().submit(() -> {
+        SystemServerInitThreadPool.submit(() -> {
             mAllowedUid = getAllowedUid(UserHandle.USER_SYSTEM);
             enforceChecksumValidity();
             formatIfOemUnlockEnabled();
diff --git a/services/core/java/com/android/server/SystemServerInitThreadPool.java b/services/core/java/com/android/server/SystemServerInitThreadPool.java
index ff6a537..5ed94e3 100644
--- a/services/core/java/com/android/server/SystemServerInitThreadPool.java
+++ b/services/core/java/com/android/server/SystemServerInitThreadPool.java
@@ -16,10 +16,12 @@
 
 package com.android.server;
 
+import android.annotation.NonNull;
 import android.os.Build;
 import android.os.Process;
 import android.util.Slog;
 
+import com.android.internal.annotations.GuardedBy;
 import com.android.internal.util.ConcurrentUtils;
 import com.android.internal.util.Preconditions;
 import com.android.server.am.ActivityManagerService;
@@ -32,9 +34,11 @@
 
 /**
  * Thread pool used during initialization of system server.
+ *
  * <p>System services can {@link #submit(Runnable)} tasks for execution during boot.
  * The pool will be shut down after {@link SystemService#PHASE_BOOT_COMPLETED}.
- * New tasks <em>should not</em> be submitted afterwards.
+ *
+ * <p>New tasks <em>should not</em> be submitted afterwards.
  *
  * @hide
  */
@@ -42,26 +46,49 @@
     private static final String TAG = SystemServerInitThreadPool.class.getSimpleName();
     private static final int SHUTDOWN_TIMEOUT_MILLIS = 20000;
     private static final boolean IS_DEBUGGABLE = Build.IS_DEBUGGABLE;
+    private static final Object LOCK = new Object();
 
+    @GuardedBy("LOCK")
     private static SystemServerInitThreadPool sInstance;
 
-    private ExecutorService mService = ConcurrentUtils.newFixedThreadPool(
-            Runtime.getRuntime().availableProcessors(),
-            "system-server-init-thread", Process.THREAD_PRIORITY_FOREGROUND);
+    private final ExecutorService mService;
 
-    private List<String> mPendingTasks = new ArrayList<>();
+    @GuardedBy("mPendingTasks")
+    private final List<String> mPendingTasks = new ArrayList<>();
 
-    public static synchronized SystemServerInitThreadPool get() {
-        if (sInstance == null) {
-            sInstance = new SystemServerInitThreadPool();
-        }
-        Preconditions.checkState(sInstance.mService != null, "Cannot get " + TAG
-                + " - it has been shut down");
-        return sInstance;
+    @GuardedBy("mPendingTasks")
+    private boolean mShutDown;
+
+    private SystemServerInitThreadPool() {
+        final int size = Runtime.getRuntime().availableProcessors();
+        Slog.i(TAG, "Creating instance with " + size + " threads");
+        mService = ConcurrentUtils.newFixedThreadPool(size,
+                "system-server-init-thread", Process.THREAD_PRIORITY_FOREGROUND);
     }
 
-    public Future<?> submit(Runnable runnable, String description) {
+    /**
+     * Submits a task for execution.
+     *
+     * @throws IllegalStateException if it hasn't been started or has been shut down already.
+     */
+    public static @NonNull Future<?> submit(@NonNull Runnable runnable,
+            @NonNull String description) {
+        Preconditions.checkNotNull(description, "description cannot be null");
+
+        SystemServerInitThreadPool instance;
+        synchronized (LOCK) {
+            Preconditions.checkState(sInstance != null, "Cannot get " + TAG
+                    + " - it has been shut down");
+            instance = sInstance;
+        }
+
+        return instance.submitTask(runnable, description);
+    }
+
+    private @NonNull Future<?> submitTask(@NonNull Runnable runnable,
+            @NonNull String description) {
         synchronized (mPendingTasks) {
+            Preconditions.checkState(!mShutDown, TAG + " already shut down");
             mPendingTasks.add(description);
         }
         return mService.submit(() -> {
@@ -83,10 +110,36 @@
         });
     }
 
-    static synchronized void shutdown() {
-        if (sInstance != null && sInstance.mService != null) {
+    /**
+     * Starts it.
+     *
+     * <p>Note:</p> should only be called by {@link SystemServer}.
+     *
+     * @throws IllegalStateException if it has been started already without being shut down yet.
+     */
+    static void start() {
+        synchronized (LOCK) {
+            Preconditions.checkState(sInstance == null, TAG + " already started");
+            sInstance = new SystemServerInitThreadPool();
+        }
+    }
+
+    /**
+     * Shuts it down.
+     *
+     * <p>Note:</p> should only be called by {@link SystemServer}.
+     */
+    static void shutdown() {
+        synchronized (LOCK) {
+            if (sInstance == null) {
+                Slog.wtf(TAG, "Already shutdown", new Exception());
+                return;
+            }
+            synchronized (sInstance.mPendingTasks) {
+                sInstance.mShutDown = true;
+            }
             sInstance.mService.shutdown();
-            boolean terminated;
+            final boolean terminated;
             try {
                 terminated = sInstance.mService.awaitTermination(SHUTDOWN_TIMEOUT_MILLIS,
                         TimeUnit.MILLISECONDS);
@@ -100,7 +153,7 @@
                 // in the thread pool.
                 dumpStackTraces();
             }
-            List<Runnable> unstartedRunnables = sInstance.mService.shutdownNow();
+            final List<Runnable> unstartedRunnables = sInstance.mService.shutdownNow();
             if (!terminated) {
                 final List<String> copy = new ArrayList<>();
                 synchronized (sInstance.mPendingTasks) {
@@ -109,8 +162,7 @@
                 throw new IllegalStateException("Cannot shutdown. Unstarted tasks "
                         + unstartedRunnables + " Unfinished tasks " + copy);
             }
-            sInstance.mService = null; // Make mService eligible for GC
-            sInstance.mPendingTasks = null;
+            sInstance = null; // Make eligible for GC
             Slog.d(TAG, "Shutdown successful");
         }
     }
diff --git a/services/core/java/com/android/server/TelephonyRegistry.java b/services/core/java/com/android/server/TelephonyRegistry.java
index f91cf0c..447ed59 100644
--- a/services/core/java/com/android/server/TelephonyRegistry.java
+++ b/services/core/java/com/android/server/TelephonyRegistry.java
@@ -274,8 +274,8 @@
                 PhoneStateListener.LISTEN_PRECISE_DATA_CONNECTION_STATE;
 
     static final int READ_ACTIVE_EMERGENCY_SESSION_PERMISSION_MASK =
-            PhoneStateListener.LISTEN_OUTGOING_CALL_EMERGENCY_NUMBER
-                    | PhoneStateListener.LISTEN_OUTGOING_SMS_EMERGENCY_NUMBER;
+            PhoneStateListener.LISTEN_OUTGOING_EMERGENCY_CALL
+                    | PhoneStateListener.LISTEN_OUTGOING_EMERGENCY_SMS;
 
     private static final int MSG_USER_SWITCHED = 1;
     private static final int MSG_UPDATE_DEFAULT_SUB = 2;
@@ -385,7 +385,7 @@
         mContext = context;
         mBatteryStats = BatteryStatsService.getService();
 
-        int numPhones = TelephonyManager.getDefault().getMaxPhoneCount();
+        int numPhones = TelephonyManager.getDefault().getSupportedModemCount();
         if (DBG) log("TelephonyRegistry: ctor numPhones=" + numPhones);
         mNumPhones = numPhones;
         mCallState = new int[numPhones];
@@ -1932,7 +1932,7 @@
                 mOutgoingCallEmergencyNumber[phoneId] = emergencyNumber;
                 for (Record r : mRecords) {
                     if (r.matchPhoneStateListenerEvent(
-                            PhoneStateListener.LISTEN_OUTGOING_CALL_EMERGENCY_NUMBER)
+                            PhoneStateListener.LISTEN_OUTGOING_EMERGENCY_CALL)
                                     && idMatch(r.subId, subId, phoneId)) {
                         try {
                             r.callback.onOutgoingEmergencyCall(emergencyNumber);
@@ -1957,7 +1957,7 @@
                 mOutgoingSmsEmergencyNumber[phoneId] = emergencyNumber;
                 for (Record r : mRecords) {
                     if (r.matchPhoneStateListenerEvent(
-                            PhoneStateListener.LISTEN_OUTGOING_SMS_EMERGENCY_NUMBER)
+                            PhoneStateListener.LISTEN_OUTGOING_EMERGENCY_SMS)
                                     && idMatch(r.subId, subId, phoneId)) {
                         try {
                             r.callback.onOutgoingEmergencySms(emergencyNumber);
diff --git a/services/core/java/com/android/server/UiModeManagerService.java b/services/core/java/com/android/server/UiModeManagerService.java
index b9d7c68..a517467 100644
--- a/services/core/java/com/android/server/UiModeManagerService.java
+++ b/services/core/java/com/android/server/UiModeManagerService.java
@@ -288,7 +288,7 @@
         updateNightModeFromSettings(context, res, UserHandle.getCallingUserId());
 
         // Update the initial, static configurations.
-        SystemServerInitThreadPool.get().submit(() -> {
+        SystemServerInitThreadPool.submit(() -> {
             synchronized (mLock) {
                 updateConfigurationLocked();
                 sendConfigurationLocked();
diff --git a/services/core/java/com/android/server/VibratorService.java b/services/core/java/com/android/server/VibratorService.java
index 9936d73..d622fb4 100644
--- a/services/core/java/com/android/server/VibratorService.java
+++ b/services/core/java/com/android/server/VibratorService.java
@@ -29,6 +29,7 @@
 import android.database.ContentObserver;
 import android.hardware.input.InputManager;
 import android.hardware.vibrator.V1_0.EffectStrength;
+import android.hardware.vibrator.V1_4.Capabilities;
 import android.icu.text.DateFormat;
 import android.media.AudioAttributes;
 import android.media.AudioManager;
@@ -108,6 +109,9 @@
     // If a vibration is playing for longer than 5s, it's probably not haptic feedback.
     private static final long MAX_HAPTIC_FEEDBACK_DURATION = 5000;
 
+    // If HAL supports callbacks set the timeout to ASYNC_TIMEOUT_MULTIPLIER * duration.
+    private static final long ASYNC_TIMEOUT_MULTIPLIER = 2;
+
 
     // A mapping from the intensity adjustment to the scaling to apply, where the intensity
     // adjustment is defined as the delta between the default intensity level and the user selected
@@ -123,6 +127,7 @@
     private final boolean mAllowPriorityVibrationsInLowPowerMode;
     private final boolean mSupportsAmplitudeControl;
     private final boolean mSupportsExternalControl;
+    private final long mCapabilities;
     private final int mDefaultVibrationAmplitude;
     private final SparseArray<VibrationEffect> mFallbackEffects;
     private final SparseArray<Integer> mProcStatesCache = new SparseArray();
@@ -163,9 +168,10 @@
     static native void vibratorOff();
     static native boolean vibratorSupportsAmplitudeControl();
     static native void vibratorSetAmplitude(int amplitude);
-    static native long vibratorPerformEffect(long effect, long strength);
+    static native long vibratorPerformEffect(long effect, long strength, Vibration vibration);
     static native boolean vibratorSupportsExternalControl();
     static native void vibratorSetExternalControl(boolean enabled);
+    static native long vibratorGetCapabilities();
 
     private final IUidObserver mUidObserver = new IUidObserver.Stub() {
         @Override public void onUidStateChanged(int uid, int procState, long procStateSeq) {
@@ -226,6 +232,14 @@
             }
         }
 
+        private void onComplete() {
+            synchronized (mLock) {
+                if (this == mCurrentVibration) {
+                    doCancelVibrateLocked();
+                }
+            }
+        }
+
         public boolean hasTimeoutLongerThan(long millis) {
             final long duration = effect.getDuration();
             return duration >= 0 && duration > millis;
@@ -347,6 +361,7 @@
 
         mSupportsAmplitudeControl = vibratorSupportsAmplitudeControl();
         mSupportsExternalControl = vibratorSupportsExternalControl();
+        mCapabilities = vibratorGetCapabilities();
 
         mContext = context;
         PowerManager pm = (PowerManager)context.getSystemService(Context.POWER_SERVICE);
@@ -1135,10 +1150,14 @@
             }
             // Input devices don't support prebaked effect, so skip trying it with them.
             if (!usingInputDeviceVibrators) {
-                long timeout = vibratorPerformEffect(prebaked.getId(),
-                        prebaked.getEffectStrength());
+                long duration = vibratorPerformEffect(prebaked.getId(),
+                        prebaked.getEffectStrength(), vib);
+                long timeout = duration;
+                if ((mCapabilities & Capabilities.PERFORM_COMPLETION_CALLBACK) != 0) {
+                    timeout *= ASYNC_TIMEOUT_MULTIPLIER;
+                }
                 if (timeout > 0) {
-                    noteVibratorOnLocked(vib.uid, timeout);
+                    noteVibratorOnLocked(vib.uid, duration);
                     return timeout;
                 }
             }
diff --git a/services/core/java/com/android/server/am/ActiveServices.java b/services/core/java/com/android/server/am/ActiveServices.java
index 08f75e6..9209a21 100644
--- a/services/core/java/com/android/server/am/ActiveServices.java
+++ b/services/core/java/com/android/server/am/ActiveServices.java
@@ -192,34 +192,38 @@
         @Override
         public void stopForegroundServicesForUidPackage(final int uid, final String packageName) {
             synchronized (mAm) {
-                final ServiceMap smap = getServiceMapLocked(UserHandle.getUserId(uid));
-                final int N = smap.mServicesByInstanceName.size();
-                final ArrayList<ServiceRecord> toStop = new ArrayList<>(N);
-                for (int i = 0; i < N; i++) {
-                    final ServiceRecord r = smap.mServicesByInstanceName.valueAt(i);
-                    if (uid == r.serviceInfo.applicationInfo.uid
-                            || packageName.equals(r.serviceInfo.packageName)) {
-                        if (r.isForeground) {
-                            toStop.add(r);
-                        }
-                    }
-                }
+                stopAllForegroundServicesLocked(uid, packageName);
+            }
+        }
+    }
 
-                // Now stop them all
-                final int numToStop = toStop.size();
-                if (numToStop > 0 && DEBUG_FOREGROUND_SERVICE) {
-                    Slog.i(TAG, "Package " + packageName + "/" + uid
-                            + " entering FAS with foreground services");
-                }
-                for (int i = 0; i < numToStop; i++) {
-                    final ServiceRecord r = toStop.get(i);
-                    if (DEBUG_FOREGROUND_SERVICE) {
-                        Slog.i(TAG, "  Stopping fg for service " + r);
-                    }
-                    setServiceForegroundInnerLocked(r, 0, null, 0, 0);
+    void stopAllForegroundServicesLocked(final int uid, final String packageName) {
+        final ServiceMap smap = getServiceMapLocked(UserHandle.getUserId(uid));
+        final int N = smap.mServicesByInstanceName.size();
+        final ArrayList<ServiceRecord> toStop = new ArrayList<>(N);
+        for (int i = 0; i < N; i++) {
+            final ServiceRecord r = smap.mServicesByInstanceName.valueAt(i);
+            if (uid == r.serviceInfo.applicationInfo.uid
+                    || packageName.equals(r.serviceInfo.packageName)) {
+                if (r.isForeground) {
+                    toStop.add(r);
                 }
             }
         }
+
+        // Now stop them all
+        final int numToStop = toStop.size();
+        if (numToStop > 0 && DEBUG_FOREGROUND_SERVICE) {
+            Slog.i(TAG, "Package " + packageName + "/" + uid
+                    + " in FAS with foreground services");
+        }
+        for (int i = 0; i < numToStop; i++) {
+            final ServiceRecord r = toStop.get(i);
+            if (DEBUG_FOREGROUND_SERVICE) {
+                Slog.i(TAG, "  Stopping fg for service " + r);
+            }
+            setServiceForegroundInnerLocked(r, 0, null, 0, 0);
+        }
     }
 
     /**
@@ -1019,12 +1023,23 @@
                         }
                     }
                     if (!aa.mAppOnTop) {
-                        if (active == null) {
-                            active = new ArrayList<>();
+                        // Transitioning a fg-service host app out of top: if it's bg restricted,
+                        // it loses the fg service state now.
+                        if (!appRestrictedAnyInBackground(aa.mUid, aa.mPackageName)) {
+                            if (active == null) {
+                                active = new ArrayList<>();
+                            }
+                            if (DEBUG_FOREGROUND_SERVICE) Slog.d(TAG, "Adding active: pkg="
+                                    + aa.mPackageName + ", uid=" + aa.mUid);
+                            active.add(aa);
+                        } else {
+                            if (DEBUG_FOREGROUND_SERVICE) {
+                                Slog.d(TAG, "bg-restricted app "
+                                        + aa.mPackageName + "/" + aa.mUid
+                                        + " exiting top; demoting fg services ");
+                            }
+                            stopAllForegroundServicesLocked(aa.mUid, aa.mPackageName);
                         }
-                        if (DEBUG_FOREGROUND_SERVICE) Slog.d(TAG, "Adding active: pkg="
-                                + aa.mPackageName + ", uid=" + aa.mUid);
-                        active.add(aa);
                     }
                 }
                 smap.removeMessages(ServiceMap.MSG_UPDATE_FOREGROUND_APPS);
diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java
index ee98af4..8c672a1 100644
--- a/services/core/java/com/android/server/am/ActivityManagerService.java
+++ b/services/core/java/com/android/server/am/ActivityManagerService.java
@@ -350,6 +350,7 @@
 import com.android.server.am.ActivityManagerServiceDumpProcessesProto.UidObserverRegistrationProto;
 import com.android.server.appop.AppOpsService;
 import com.android.server.compat.CompatConfig;
+import com.android.server.compat.PlatformCompat;
 import com.android.server.contentcapture.ContentCaptureManagerInternal;
 import com.android.server.firewall.IntentFirewall;
 import com.android.server.job.JobSchedulerInternal;
@@ -1575,6 +1576,8 @@
     // Encapsulates the global setting "hidden_api_blacklist_exemptions"
     final HiddenApiSettings mHiddenApiBlacklist;
 
+    private final PlatformCompat mPlatformCompat;
+
     PackageManagerInternal mPackageManagerInt;
     PermissionManagerServiceInternal mPermissionManagerInt;
 
@@ -2427,6 +2430,7 @@
         mFactoryTest = FACTORY_TEST_OFF;
         mUgmInternal = LocalServices.getService(UriGrantsManagerInternal.class);
         mInternal = new LocalService();
+        mPlatformCompat = null;
     }
 
     // Note: This method is invoked on the main thread but may need to attach various
@@ -2563,6 +2567,9 @@
 
         mHiddenApiBlacklist = new HiddenApiSettings(mHandler, mContext);
 
+        mPlatformCompat = (PlatformCompat) ServiceManager.getService(
+                Context.PLATFORM_COMPAT_SERVICE);
+
         Watchdog.getInstance().addMonitor(this);
         Watchdog.getInstance().addThread(mHandler);
 
@@ -5015,7 +5022,9 @@
             if (preBindAgent != null) {
                 thread.attachAgent(preBindAgent);
             }
-
+            if ((app.info.flags & ApplicationInfo.FLAG_DEBUGGABLE) != 0) {
+                thread.attachStartupAgents(app.info.dataDir);
+            }
 
             // Figure out whether the app needs to run in autofill compat mode.
             AutofillOptions autofillOptions = null;
@@ -5042,6 +5051,9 @@
             mAtmInternal.preBindApplication(app.getWindowProcessController());
             final ActiveInstrumentation instr2 = app.getActiveInstrumentation();
             long[] disabledCompatChanges = CompatConfig.get().getDisabledChanges(app.info);
+            if (mPlatformCompat != null) {
+                mPlatformCompat.resetReporting(app.info);
+            }
             if (app.isolatedEntryPoint != null) {
                 // This is an isolated process which should just call an entry point instead of
                 // being bound to an application.
@@ -9736,6 +9748,10 @@
             sb.append("Foreground: ")
                     .append(process.isInterestingToUserLocked() ? "Yes" : "No")
                     .append("\n");
+            if (process.startTime > 0) {
+                long runtimeMillis = SystemClock.elapsedRealtime() - process.startTime;
+                sb.append("Process-Runtime: ").append(runtimeMillis).append("\n");
+            }
         }
         if (activityShortComponentName != null) {
             sb.append("Activity: ").append(activityShortComponentName).append("\n");
@@ -18349,7 +18365,7 @@
 
         @Override
         public int getCurrentUserId() {
-            return mUserController.getCurrentUserIdLU();
+            return mUserController.getCurrentUserId();
         }
 
         @Override
diff --git a/services/core/java/com/android/server/am/ActivityManagerShellCommand.java b/services/core/java/com/android/server/am/ActivityManagerShellCommand.java
index 058afd3..8be2438 100644
--- a/services/core/java/com/android/server/am/ActivityManagerShellCommand.java
+++ b/services/core/java/com/android/server/am/ActivityManagerShellCommand.java
@@ -2859,7 +2859,21 @@
         return 0;
     }
 
-    private int runCompat(PrintWriter pw) {
+    private void killPackage(String packageName, PrintWriter pw) throws RemoteException {
+        int uid = mPm.getPackageUid(packageName, 0, mUserId);
+        if (uid < 0) {
+            // uid is negative if the package wasn't found.
+            pw.println("Didn't find package " + packageName + " on device.");
+        } else {
+            pw.println("Killing package " + packageName + " (UID " + uid + ").");
+            final long origId = Binder.clearCallingIdentity();
+            mInterface.killUid(UserHandle.getAppId(uid),
+                    UserHandle.USER_ALL, "killPackage");
+            Binder.restoreCallingIdentity(origId);
+        }
+    }
+
+    private int runCompat(PrintWriter pw) throws RemoteException {
         final CompatConfig config = CompatConfig.get();
         String toggleValue = getNextArgRequired();
         long changeId;
@@ -2873,13 +2887,14 @@
             pw.println("Unknown or invalid change: '" + changeIdString + "'.");
         }
         String packageName = getNextArgRequired();
-        switch(toggleValue) {
+        switch (toggleValue) {
             case "enable":
                 if (!config.addOverride(changeId, packageName, true)) {
                     pw.println("Warning! Change " + changeId + " is not known yet. Enabling it"
                             + " could have no effect.");
                 }
                 pw.println("Enabled change " + changeId + " for " + packageName + ".");
+                killPackage(packageName, pw);
                 return 0;
             case "disable":
                 if (!config.addOverride(changeId, packageName, false)) {
@@ -2887,11 +2902,13 @@
                             + " could have no effect.");
                 }
                 pw.println("Disabled change " + changeId + " for " + packageName + ".");
+                killPackage(packageName, pw);
                 return 0;
             case "reset":
                 if (config.removeOverride(changeId, packageName)) {
                     pw.println("Reset change " + changeId + " for " + packageName
                             + " to default value.");
+                    killPackage(packageName, pw);
                 } else {
                     pw.println("No override exists for changeId " + changeId + ".");
                 }
@@ -3210,6 +3227,7 @@
             pw.println("      Write all pending state to storage.");
             pw.println("  compat enable|disable|reset <CHANGE_ID|CHANGE_NAME> <PACKAGE_NAME>");
             pw.println("      Toggles a change either by id or by name for <PACKAGE_NAME>.");
+            pw.println("      It kills <PACKAGE_NAME> (to allow the toggle to take effect).");
             pw.println();
             Intent.printIntentArgsHelp(pw, "");
         }
diff --git a/services/core/java/com/android/server/am/OomAdjuster.java b/services/core/java/com/android/server/am/OomAdjuster.java
index 3c2aee4..bb214bd 100644
--- a/services/core/java/com/android/server/am/OomAdjuster.java
+++ b/services/core/java/com/android/server/am/OomAdjuster.java
@@ -30,7 +30,7 @@
 import static android.app.ActivityManager.PROCESS_STATE_TOP;
 import static android.app.ActivityManager.PROCESS_STATE_TRANSIENT_BACKGROUND;
 import static android.os.Process.SCHED_OTHER;
-import static android.os.Process.THREAD_GROUP_BG_NONINTERACTIVE;
+import static android.os.Process.THREAD_GROUP_BACKGROUND;
 import static android.os.Process.THREAD_GROUP_DEFAULT;
 import static android.os.Process.THREAD_GROUP_RESTRICTED;
 import static android.os.Process.THREAD_GROUP_TOP_APP;
@@ -1759,7 +1759,7 @@
                 int processGroup;
                 switch (curSchedGroup) {
                     case ProcessList.SCHED_GROUP_BACKGROUND:
-                        processGroup = THREAD_GROUP_BG_NONINTERACTIVE;
+                        processGroup = THREAD_GROUP_BACKGROUND;
                         break;
                     case ProcessList.SCHED_GROUP_TOP_APP:
                     case ProcessList.SCHED_GROUP_TOP_APP_BOUND:
diff --git a/services/core/java/com/android/server/am/ProcessList.java b/services/core/java/com/android/server/am/ProcessList.java
index c0af814..af126f2 100644
--- a/services/core/java/com/android/server/am/ProcessList.java
+++ b/services/core/java/com/android/server/am/ProcessList.java
@@ -215,7 +215,7 @@
     // Memory pages are 4K.
     static final int PAGE_SIZE = 4 * 1024;
 
-    // Activity manager's version of Process.THREAD_GROUP_BG_NONINTERACTIVE
+    // Activity manager's version of Process.THREAD_GROUP_BACKGROUND
     static final int SCHED_GROUP_BACKGROUND = 0;
       // Activity manager's version of Process.THREAD_GROUP_RESTRICTED
     static final int SCHED_GROUP_RESTRICTED = 1;
diff --git a/services/core/java/com/android/server/am/ProcessStatsService.java b/services/core/java/com/android/server/am/ProcessStatsService.java
index 6ffd8a9..5c840ad 100644
--- a/services/core/java/com/android/server/am/ProcessStatsService.java
+++ b/services/core/java/com/android/server/am/ProcessStatsService.java
@@ -1101,7 +1101,7 @@
         }
 
         boolean sepNeeded = false;
-        if (dumpAll || isCheckin) {
+        if ((dumpAll || isCheckin) && !currentOnly) {
             mWriteLock.lock();
             try {
                 ArrayList<String> files = getCommittedFiles(0, false, !isCheckin);
diff --git a/services/core/java/com/android/server/am/TEST_MAPPING b/services/core/java/com/android/server/am/TEST_MAPPING
index 21d4925..bc4707f 100644
--- a/services/core/java/com/android/server/am/TEST_MAPPING
+++ b/services/core/java/com/android/server/am/TEST_MAPPING
@@ -33,7 +33,6 @@
     },
     {
       "name": "FrameworksMockingServicesTests",
-      "file_patterns": ["AppCompactor\\.java"],
       "options": [
         {
           "include-filter": "com.android.server.am."
diff --git a/services/core/java/com/android/server/am/UserController.java b/services/core/java/com/android/server/am/UserController.java
index 5c8e530..17541911 100644
--- a/services/core/java/com/android/server/am/UserController.java
+++ b/services/core/java/com/android/server/am/UserController.java
@@ -133,12 +133,12 @@
     static final int CONTINUE_USER_SWITCH_MSG = 20;
     static final int USER_SWITCH_TIMEOUT_MSG = 30;
     static final int START_PROFILES_MSG = 40;
-    static final int SYSTEM_USER_START_MSG = 50;
-    static final int SYSTEM_USER_CURRENT_MSG = 60;
+    static final int USER_START_MSG = 50;
+    static final int USER_CURRENT_MSG = 60;
     static final int FOREGROUND_PROFILE_CHANGED_MSG = 70;
     static final int REPORT_USER_SWITCH_COMPLETE_MSG = 80;
     static final int USER_SWITCH_CALLBACKS_TIMEOUT_MSG = 90;
-    static final int SYSTEM_USER_UNLOCK_MSG = 100;
+    static final int USER_UNLOCK_MSG = 100;
     static final int REPORT_LOCKED_BOOT_COMPLETE_MSG = 110;
     static final int START_USER_SWITCH_FG_MSG = 120;
 
@@ -368,16 +368,18 @@
                 }
             }
 
-            mHandler.sendMessage(mHandler.obtainMessage(REPORT_LOCKED_BOOT_COMPLETE_MSG,
-                    userId, 0));
-            Intent intent = new Intent(Intent.ACTION_LOCKED_BOOT_COMPLETED, null);
-            intent.putExtra(Intent.EXTRA_USER_HANDLE, userId);
-            intent.addFlags(Intent.FLAG_RECEIVER_NO_ABORT
-                    | Intent.FLAG_RECEIVER_INCLUDE_BACKGROUND);
-            mInjector.broadcastIntent(intent, null, resultTo, 0, null, null,
-                    new String[]{android.Manifest.permission.RECEIVE_BOOT_COMPLETED},
-                    AppOpsManager.OP_NONE, null, true, false, MY_PID, SYSTEM_UID,
-                    Binder.getCallingUid(), Binder.getCallingPid(), userId);
+            if (!mInjector.getUserManager().isPreCreated(userId)) {
+                mHandler.sendMessage(mHandler.obtainMessage(REPORT_LOCKED_BOOT_COMPLETE_MSG,
+                        userId, 0));
+                Intent intent = new Intent(Intent.ACTION_LOCKED_BOOT_COMPLETED, null);
+                intent.putExtra(Intent.EXTRA_USER_HANDLE, userId);
+                intent.addFlags(Intent.FLAG_RECEIVER_NO_ABORT
+                        | Intent.FLAG_RECEIVER_INCLUDE_BACKGROUND);
+                mInjector.broadcastIntent(intent, null, resultTo, 0, null, null,
+                        new String[]{android.Manifest.permission.RECEIVE_BOOT_COMPLETED},
+                        AppOpsManager.OP_NONE, null, true, false, MY_PID, SYSTEM_UID,
+                        Binder.getCallingUid(), Binder.getCallingPid(), userId);
+            }
         }
 
         // We need to delay unlocking managed profiles until the parent user
@@ -438,8 +440,7 @@
 
             // Dispatch unlocked to system services; when fully dispatched,
             // that calls through to the next "unlocked" phase
-            mHandler.obtainMessage(SYSTEM_USER_UNLOCK_MSG, userId, 0, uss)
-                    .sendToTarget();
+            mHandler.obtainMessage(USER_UNLOCK_MSG, userId, 0, uss).sendToTarget();
         });
         return true;
     }
@@ -555,6 +556,17 @@
             }
         }
 
+        if (userInfo.preCreated) {
+            Slog.i(TAG, "Stopping pre-created user " + userInfo.toFullString());
+            // Pre-created user was started right after creation so services could properly
+            // intialize it; it should be stopped right away as it's not really a "real" user.
+            // TODO(b/140750212): in the long-term, we should add a onCreateUser() callback
+            // on SystemService instead.
+            stopUser(userInfo.id, /* force= */ true, /* stopUserCallback= */ null,
+                    /* keyEvictedCallback= */ null);
+            return;
+        }
+
         // Spin up app widgets prior to boot-complete, so they can be ready promptly
         mInjector.startUserWidgets(userId);
 
@@ -799,7 +811,8 @@
             mInjector.systemServiceManagerCleanupUser(userId);
             mInjector.stackSupervisorRemoveUser(userId);
             // Remove the user if it is ephemeral.
-            if (getUserInfo(userId).isEphemeral()) {
+            UserInfo userInfo = getUserInfo(userId);
+            if (userInfo.isEphemeral() && !userInfo.preCreated) {
                 mInjector.getUserManager().removeUserEvenWhenDisallowed(userId);
             }
 
@@ -1069,6 +1082,11 @@
                 return false;
             }
 
+            if (foreground && userInfo.preCreated) {
+                Slog.w(TAG, "Cannot start pre-created user #" + userId + " as foreground");
+                return false;
+            }
+
             if (foreground && mUserSwitchUiEnabled) {
                 t.traceBegin("startFreezingScreen");
                 mInjector.getWindowManager().startFreezingScreen(
@@ -1166,7 +1184,7 @@
                     updateStartedUserArrayLU();
                 }
                 needStart = true;
-                t.traceBegin("updateStateStopping");
+                t.traceEnd();
             }
 
             if (uss.state == UserState.STATE_BOOTING) {
@@ -1178,15 +1196,13 @@
                 // Booting up a new user, need to tell system services about it.
                 // Note that this is on the same handler as scheduling of broadcasts,
                 // which is important because it needs to go first.
-                mHandler.sendMessage(
-                        mHandler.obtainMessage(SYSTEM_USER_START_MSG, userId, 0));
+                mHandler.sendMessage(mHandler.obtainMessage(USER_START_MSG, userId, 0));
                 t.traceEnd();
             }
 
             t.traceBegin("sendMessages");
             if (foreground) {
-                mHandler.sendMessage(mHandler.obtainMessage(SYSTEM_USER_CURRENT_MSG, userId,
-                        oldUserId));
+                mHandler.sendMessage(mHandler.obtainMessage(USER_CURRENT_MSG, userId, oldUserId));
                 mHandler.removeMessages(REPORT_USER_SWITCH_MSG);
                 mHandler.removeMessages(USER_SWITCH_TIMEOUT_MSG);
                 mHandler.sendMessage(mHandler.obtainMessage(REPORT_USER_SWITCH_MSG,
@@ -1195,6 +1211,10 @@
                         oldUserId, userId, uss), USER_SWITCH_TIMEOUT_MS);
             }
 
+            if (userInfo.preCreated) {
+                needStart = false;
+            }
+
             if (needStart) {
                 // Send USER_STARTED broadcast
                 Intent intent = new Intent(Intent.ACTION_USER_STARTED);
@@ -2168,14 +2188,14 @@
             case START_PROFILES_MSG:
                 startProfiles();
                 break;
-            case SYSTEM_USER_START_MSG:
+            case USER_START_MSG:
                 mInjector.batteryStatsServiceNoteEvent(
                         BatteryStats.HistoryItem.EVENT_USER_RUNNING_START,
                         Integer.toString(msg.arg1), msg.arg1);
                 mInjector.getSystemServiceManager().startUser(TimingsTraceAndSlog.newAsyncLog(),
                         msg.arg1);
                 break;
-            case SYSTEM_USER_UNLOCK_MSG:
+            case USER_UNLOCK_MSG:
                 final int userId = msg.arg1;
                 mInjector.getSystemServiceManager().unlockUser(userId);
                 // Loads recents on a worker thread that allows disk I/O
@@ -2184,7 +2204,7 @@
                 });
                 finishUserUnlocked((UserState) msg.obj);
                 break;
-            case SYSTEM_USER_CURRENT_MSG:
+            case USER_CURRENT_MSG:
                 mInjector.batteryStatsServiceNoteEvent(
                         BatteryStats.HistoryItem.EVENT_USER_FOREGROUND_FINISH,
                         Integer.toString(msg.arg2), msg.arg2);
diff --git a/services/core/java/com/android/server/appop/AppOpsService.java b/services/core/java/com/android/server/appop/AppOpsService.java
index 798185a..6c4cc2d 100644
--- a/services/core/java/com/android/server/appop/AppOpsService.java
+++ b/services/core/java/com/android/server/appop/AppOpsService.java
@@ -65,7 +65,6 @@
 import android.content.pm.UserInfo;
 import android.database.ContentObserver;
 import android.hardware.camera2.CameraDevice.CAMERA_AUDIO_RESTRICTION;
-import android.media.AudioAttributes;
 import android.net.Uri;
 import android.os.AsyncTask;
 import android.os.Binder;
@@ -109,6 +108,7 @@
 import com.android.internal.app.IAppOpsService;
 import com.android.internal.os.Zygote;
 import com.android.internal.util.ArrayUtils;
+import com.android.internal.util.CollectionUtils;
 import com.android.internal.util.DumpUtils;
 import com.android.internal.util.FastXmlSerializer;
 import com.android.internal.util.Preconditions;
@@ -257,6 +257,9 @@
     @GuardedBy("this")
     private CheckOpsDelegate mCheckOpsDelegate;
 
+    @GuardedBy("this")
+    private SparseArray<List<Integer>> mSwitchOpToOps;
+
     /**
      * All times are in milliseconds. These constants are kept synchronized with the system
      * global Settings. Any access to this class or its fields should be done while
@@ -1291,6 +1294,8 @@
         verifyIncomingOp(code);
         code = AppOpsManager.opToSwitch(code);
 
+        updatePermissionRevokedCompat(uid, code, mode);
+
         synchronized (this) {
             final int defaultMode = AppOpsManager.opToDefaultMode(code);
 
@@ -1392,6 +1397,86 @@
         notifyOpChangedSync(code, uid, null, mode);
     }
 
+    private void updatePermissionRevokedCompat(int uid, int switchCode, int mode) {
+        PackageManager packageManager = mContext.getPackageManager();
+        String[] packageNames = packageManager.getPackagesForUid(uid);
+        if (ArrayUtils.isEmpty(packageNames)) {
+            return;
+        }
+        String packageName = packageNames[0];
+
+        List<Integer> ops = getSwitchOpToOps().get(switchCode);
+        int opsSize = CollectionUtils.size(ops);
+        for (int i = 0; i < opsSize; i++) {
+            int code = ops.get(i);
+
+            String permissionName = AppOpsManager.opToPermission(code);
+            if (permissionName == null) {
+                continue;
+            }
+
+            PermissionInfo permissionInfo;
+            try {
+                permissionInfo = packageManager.getPermissionInfo(permissionName, 0);
+            } catch (PackageManager.NameNotFoundException e) {
+                e.printStackTrace();
+                continue;
+            }
+
+            if (!permissionInfo.isRuntime()) {
+                continue;
+            }
+
+            UserHandle user = UserHandle.getUserHandleForUid(uid);
+            boolean isRevokedCompat;
+            if (permissionInfo.backgroundPermission != null) {
+                boolean isBackgroundRevokedCompat = mode != AppOpsManager.MODE_ALLOWED;
+                long identity = Binder.clearCallingIdentity();
+                try {
+                    packageManager.updatePermissionFlags(permissionInfo.backgroundPermission,
+                            packageName, PackageManager.FLAG_PERMISSION_REVOKED_COMPAT,
+                            isBackgroundRevokedCompat
+                                    ? PackageManager.FLAG_PERMISSION_REVOKED_COMPAT : 0, user);
+                } finally {
+                    Binder.restoreCallingIdentity(identity);
+                }
+
+                isRevokedCompat = mode != AppOpsManager.MODE_ALLOWED
+                        && mode != AppOpsManager.MODE_FOREGROUND;
+            } else {
+                isRevokedCompat = mode != AppOpsManager.MODE_ALLOWED;
+            }
+
+            long identity = Binder.clearCallingIdentity();
+            try {
+                packageManager.updatePermissionFlags(permissionName, packageName,
+                        PackageManager.FLAG_PERMISSION_REVOKED_COMPAT, isRevokedCompat
+                                ? PackageManager.FLAG_PERMISSION_REVOKED_COMPAT : 0, user);
+            } finally {
+                Binder.restoreCallingIdentity(identity);
+            }
+        }
+    }
+
+    @NonNull
+    private SparseArray<List<Integer>> getSwitchOpToOps() {
+        synchronized (this) {
+            if (mSwitchOpToOps == null) {
+                mSwitchOpToOps = new SparseArray<>();
+                for (int op = 0; op < _NUM_OP; op++) {
+                    int switchOp = AppOpsManager.opToSwitch(op);
+                    List<Integer> ops = mSwitchOpToOps.get(switchOp);
+                    if (ops == null) {
+                        ops = new ArrayList<>();
+                        mSwitchOpToOps.put(switchOp, ops);
+                    }
+                    ops.add(op);
+                }
+            }
+            return mSwitchOpToOps;
+        }
+    }
+
     private void notifyOpChangedSync(int code, int uid, @NonNull String packageName, int mode) {
         final StorageManagerInternal storageManagerInternal =
                 LocalServices.getService(StorageManagerInternal.class);
diff --git a/services/core/java/com/android/server/audio/AudioService.java b/services/core/java/com/android/server/audio/AudioService.java
index e02c5be..a6ac17d 100644
--- a/services/core/java/com/android/server/audio/AudioService.java
+++ b/services/core/java/com/android/server/audio/AudioService.java
@@ -1566,12 +1566,13 @@
         AudioSystem.setMasterMute(masterMute);
         broadcastMasterMuteStatus(masterMute);
 
-        boolean microphoneMute = mUserManagerInternal.getUserRestriction(
+        mMicMuteFromRestrictions = mUserManagerInternal.getUserRestriction(
                 currentUser, UserManager.DISALLOW_UNMUTE_MICROPHONE);
         if (DEBUG_VOL) {
-            Log.d(TAG, String.format("Mic mute %s, user=%d", microphoneMute, currentUser));
+            Log.d(TAG, String.format("Mic mute %b, user=%d", mMicMuteFromRestrictions,
+                    currentUser));
         }
-        AudioSystem.muteMicrophone(microphoneMute);
+        setMicrophoneMuteNoCallerCheck(currentUser);
     }
 
     private int rescaleIndex(int index, int srcStream, int dstStream) {
@@ -2876,7 +2877,7 @@
     private void setMicrophoneMuteNoCallerCheck(int userId) {
         final boolean muted = isMicrophoneMuted();
         if (DEBUG_VOL) {
-            Log.d(TAG, String.format("Mic mute %d, user=%d", muted, userId));
+            Log.d(TAG, String.format("Mic mute %b, user=%d", muted, userId));
         }
         // only mute for the current user
         if (getCurrentUserId() == userId || userId == android.os.Process.SYSTEM_UID) {
diff --git a/services/core/java/com/android/server/biometrics/BiometricService.java b/services/core/java/com/android/server/biometrics/BiometricService.java
index 3d341ef..4f1db3c 100644
--- a/services/core/java/com/android/server/biometrics/BiometricService.java
+++ b/services/core/java/com/android/server/biometrics/BiometricService.java
@@ -26,19 +26,17 @@
 
 import android.app.ActivityManager;
 import android.app.IActivityManager;
-import android.app.KeyguardManager;
 import android.app.UserSwitchObserver;
 import android.content.ContentResolver;
 import android.content.Context;
-import android.content.Intent;
 import android.content.pm.PackageManager;
 import android.database.ContentObserver;
+import android.hardware.biometrics.Authenticator;
 import android.hardware.biometrics.BiometricAuthenticator;
 import android.hardware.biometrics.BiometricConstants;
 import android.hardware.biometrics.BiometricPrompt;
 import android.hardware.biometrics.BiometricSourceType;
 import android.hardware.biometrics.BiometricsProtoEnums;
-import android.hardware.biometrics.IBiometricConfirmDeviceCredentialCallback;
 import android.hardware.biometrics.IBiometricEnabledOnKeyguardCallback;
 import android.hardware.biometrics.IBiometricService;
 import android.hardware.biometrics.IBiometricServiceReceiver;
@@ -95,11 +93,8 @@
     private static final int MSG_ON_READY_FOR_AUTHENTICATION = 8;
     private static final int MSG_AUTHENTICATE = 9;
     private static final int MSG_CANCEL_AUTHENTICATION = 10;
-    private static final int MSG_ON_CONFIRM_DEVICE_CREDENTIAL_SUCCESS = 11;
-    private static final int MSG_ON_CONFIRM_DEVICE_CREDENTIAL_ERROR = 12;
-    private static final int MSG_REGISTER_CANCELLATION_CALLBACK = 13;
-    private static final int MSG_ON_AUTHENTICATION_TIMED_OUT = 14;
-
+    private static final int MSG_ON_AUTHENTICATION_TIMED_OUT = 11;
+    private static final int MSG_ON_DEVICE_CREDENTIAL_PRESSED = 12;
     private static final int[] FEATURE_ID = {
         TYPE_FINGERPRINT,
         TYPE_IRIS,
@@ -132,19 +127,19 @@
      */
     static final int STATE_AUTH_PENDING_CONFIRM = 5;
     /**
-     * Biometric authentication was canceled, but the device is now showing ConfirmDeviceCredential
-     */
-    static final int STATE_BIOMETRIC_AUTH_CANCELED_SHOWING_CDC = 6;
-    /**
      * Biometric authenticated, waiting for SysUI to finish animation
      */
-    static final int STATE_AUTHENTICATED_PENDING_SYSUI = 7;
+    static final int STATE_AUTHENTICATED_PENDING_SYSUI = 6;
     /**
      * Biometric error, waiting for SysUI to finish animation
      */
-    static final int STATE_ERROR_PENDING_SYSUI = 8;
+    static final int STATE_ERROR_PENDING_SYSUI = 7;
+    /**
+     * Device credential in AuthController is showing
+     */
+    static final int STATE_SHOWING_DEVICE_CREDENTIAL = 8;
 
-    final class AuthSession implements IBinder.DeathRecipient {
+    final class AuthSession {
         // Map of Authenticator/Cookie pairs. We expect to receive the cookies back from
         // <Biometric>Services before we can start authenticating. Pairs that have been returned
         // are moved to mModalitiesMatched.
@@ -184,14 +179,10 @@
         // Timestamp when hardware authentication occurred
         private long mAuthenticatedTimeMs;
 
-        // TODO(b/123378871): Remove when moved.
-        private IBiometricConfirmDeviceCredentialCallback mConfirmDeviceCredentialCallback;
-
         AuthSession(HashMap<Integer, Integer> modalities, IBinder token, long sessionId,
                 int userId, IBiometricServiceReceiver receiver, String opPackageName,
                 Bundle bundle, int callingUid, int callingPid, int callingUserId,
-                int modality, boolean requireConfirmation,
-                IBiometricConfirmDeviceCredentialCallback callback) {
+                int modality, boolean requireConfirmation) {
             mModalitiesWaiting = modalities;
             mToken = token;
             mSessionId = sessionId;
@@ -204,25 +195,12 @@
             mCallingUserId = callingUserId;
             mModality = modality;
             mRequireConfirmation = requireConfirmation;
-            mConfirmDeviceCredentialCallback = callback;
-
-            if (isFromConfirmDeviceCredential()) {
-                try {
-                    token.linkToDeath(this, 0 /* flags */);
-                } catch (RemoteException e) {
-                    Slog.e(TAG, "Unable to link to death", e);
-                }
-            }
         }
 
         boolean isCrypto() {
             return mSessionId != 0;
         }
 
-        boolean isFromConfirmDeviceCredential() {
-            return mBundle.getBoolean(BiometricPrompt.KEY_FROM_CONFIRM_DEVICE_CREDENTIAL, false);
-        }
-
         boolean containsCookie(int cookie) {
             if (mModalitiesWaiting != null && mModalitiesWaiting.containsValue(cookie)) {
                 return true;
@@ -233,23 +211,8 @@
             return false;
         }
 
-        // TODO(b/123378871): Remove when moved.
-        @Override
-        public void binderDied() {
-            mHandler.post(() -> {
-                Slog.e(TAG, "Binder died, killing ConfirmDeviceCredential");
-                if (mConfirmDeviceCredentialCallback == null) {
-                    Slog.e(TAG, "Callback is null");
-                    return;
-                }
-
-                try {
-                    mConfirmDeviceCredentialCallback.cancel();
-                    mConfirmDeviceCredentialCallback = null;
-                } catch (RemoteException e) {
-                    Slog.e(TAG, "Unable to send cancel", e);
-                }
-            });
+        boolean isAllowDeviceCredential() {
+            return Utils.isDeviceCredentialAllowed(mBundle);
         }
     }
 
@@ -275,7 +238,7 @@
 
     // Get and cache the available authenticator (manager) classes. Used since aidl doesn't support
     // polymorphism :/
-    final ArrayList<Authenticator> mAuthenticators = new ArrayList<>();
+    final ArrayList<AuthenticatorWrapper> mAuthenticators = new ArrayList<>();
 
     // The current authentication session, null if idle/done. We need to track both the current
     // and pending sessions since errors may be sent to either.
@@ -284,14 +247,6 @@
     @VisibleForTesting
     AuthSession mPendingAuthSession;
 
-    // TODO(b/123378871): Remove when moved.
-    // When BiometricPrompt#setAllowDeviceCredentials is set to true, we need to store the
-    // client (app) receiver. BiometricService internally launches CDCA which invokes
-    // BiometricService to start authentication (normal path). When auth is success/rejected,
-    // CDCA will use an aidl method to poke BiometricService - the result will then be forwarded
-    // to this receiver.
-    private IBiometricServiceReceiver mConfirmDeviceCredentialReceiver;
-
     @VisibleForTesting
     final Handler mHandler = new Handler(Looper.getMainLooper()) {
         @Override
@@ -361,8 +316,7 @@
                             (Bundle) args.arg5 /* bundle */,
                             args.argi2 /* callingUid */,
                             args.argi3 /* callingPid */,
-                            args.argi4 /* callingUserId */,
-                            (IBiometricConfirmDeviceCredentialCallback) args.arg6 /* callback */);
+                            args.argi4 /* callingUserId */);
                     args.recycle();
                     break;
                 }
@@ -376,31 +330,16 @@
                     break;
                 }
 
-                case MSG_ON_CONFIRM_DEVICE_CREDENTIAL_SUCCESS: {
-                    handleOnConfirmDeviceCredentialSuccess();
-                    break;
-                }
-
-                case MSG_ON_CONFIRM_DEVICE_CREDENTIAL_ERROR: {
-                    SomeArgs args = (SomeArgs) msg.obj;
-                    handleOnConfirmDeviceCredentialError(
-                            args.argi1 /* error */,
-                            (String) args.arg1 /* errorMsg */);
-                    args.recycle();
-                    break;
-                }
-
-                case MSG_REGISTER_CANCELLATION_CALLBACK: {
-                    handleRegisterCancellationCallback(
-                            (IBiometricConfirmDeviceCredentialCallback) msg.obj /* callback */);
-                    break;
-                }
-
                 case MSG_ON_AUTHENTICATION_TIMED_OUT: {
                     handleAuthenticationTimedOut((String) msg.obj /* errorMessage */);
                     break;
                 }
 
+                case MSG_ON_DEVICE_CREDENTIAL_PRESSED: {
+                    handleOnDeviceCredentialPressed();
+                    break;
+                }
+
                 default:
                     Slog.e(TAG, "Unknown message: " + msg);
                     break;
@@ -408,11 +347,11 @@
         }
     };
 
-    private final class Authenticator {
+    private final class AuthenticatorWrapper {
         final int mType;
         final BiometricAuthenticator mAuthenticator;
 
-        Authenticator(int type, BiometricAuthenticator authenticator) {
+        AuthenticatorWrapper(int type, BiometricAuthenticator authenticator) {
             mType = type;
             mAuthenticator = authenticator;
         }
@@ -620,6 +559,11 @@
         public void onTryAgainPressed() {
             mHandler.sendEmptyMessage(MSG_ON_TRY_AGAIN_PRESSED);
         }
+
+        @Override
+        public void onDeviceCredentialPressed() {
+            mHandler.sendEmptyMessage(MSG_ON_DEVICE_CREDENTIAL_PRESSED);
+        }
     };
 
 
@@ -642,18 +586,12 @@
 
         @Override // Binder call
         public void authenticate(IBinder token, long sessionId, int userId,
-                IBiometricServiceReceiver receiver, String opPackageName, Bundle bundle,
-                IBiometricConfirmDeviceCredentialCallback callback)
+                IBiometricServiceReceiver receiver, String opPackageName, Bundle bundle)
                 throws RemoteException {
             final int callingUid = Binder.getCallingUid();
             final int callingPid = Binder.getCallingPid();
             final int callingUserId = UserHandle.getCallingUserId();
 
-            // TODO(b/123378871): Remove when moved.
-            if (callback != null) {
-                checkInternalPermission();
-            }
-
             // In the BiometricServiceBase, check do the AppOps and foreground check.
             if (userId == callingUserId) {
                 // Check the USE_BIOMETRIC permission here.
@@ -670,12 +608,12 @@
                 return;
             }
 
-            final boolean isFromConfirmDeviceCredential =
-                    bundle.getBoolean(BiometricPrompt.KEY_FROM_CONFIRM_DEVICE_CREDENTIAL, false);
-            if (isFromConfirmDeviceCredential) {
+            if (bundle.get(BiometricPrompt.KEY_AUTHENTICATORS_ALLOWED) != null) {
                 checkInternalPermission();
             }
 
+            Utils.combineAuthenticatorBundles(bundle);
+
             // Check the usage of this in system server. Need to remove this check if it becomes
             // a public API.
             final boolean useDefaultTitle =
@@ -689,39 +627,6 @@
                 }
             }
 
-            // Launch CDC instead if necessary. CDC will return results through an AIDL call, since
-            // we can't get activity results. Store the receiver somewhere so we can forward the
-            // result back to the client.
-            // TODO(b/123378871): Remove when moved.
-            if (bundle.getBoolean(BiometricPrompt.KEY_ALLOW_DEVICE_CREDENTIAL)) {
-                mHandler.post(() -> {
-                    final KeyguardManager kgm = getContext().getSystemService(
-                            KeyguardManager.class);
-                    if (!kgm.isDeviceSecure()) {
-                        try {
-                            receiver.onError(
-                                    BiometricConstants.BIOMETRIC_ERROR_NO_DEVICE_CREDENTIAL,
-                                    getContext().getString(
-                                            R.string.biometric_error_device_not_secured));
-                        } catch (RemoteException e) {
-                            Slog.e(TAG, "Remote exception", e);
-                        }
-                        return;
-                    }
-                    mConfirmDeviceCredentialReceiver = receiver;
-                    // Use this so we don't need to duplicate logic..
-                    final Intent intent = kgm.createConfirmDeviceCredentialIntent(null /* title */,
-                            null /* description */, userId);
-                    // Then give it the bundle to do magic behavior..
-                    intent.putExtra(KeyguardManager.EXTRA_BIOMETRIC_PROMPT_BUNDLE, bundle);
-                    // Create a new task with this activity located at the root.
-                    intent.setFlags(
-                            Intent.FLAG_ACTIVITY_MULTIPLE_TASK | Intent.FLAG_ACTIVITY_NEW_DOCUMENT);
-                    getContext().startActivityAsUser(intent, UserHandle.CURRENT);
-                });
-                return;
-            }
-
             SomeArgs args = SomeArgs.obtain();
             args.arg1 = token;
             args.arg2 = sessionId;
@@ -732,41 +637,11 @@
             args.argi2 = callingUid;
             args.argi3 = callingPid;
             args.argi4 = callingUserId;
-            args.arg6 = callback;
 
             mHandler.obtainMessage(MSG_AUTHENTICATE, args).sendToTarget();
         }
 
         @Override // Binder call
-        public void onConfirmDeviceCredentialSuccess() {
-            checkInternalPermission();
-
-            mHandler.sendEmptyMessage(MSG_ON_CONFIRM_DEVICE_CREDENTIAL_SUCCESS);
-        }
-
-        @Override // Binder call
-        public void onConfirmDeviceCredentialError(int error, String message) {
-            checkInternalPermission();
-
-            SomeArgs args = SomeArgs.obtain();
-            args.argi1 = error;
-            args.arg1 = message;
-            mHandler.obtainMessage(MSG_ON_CONFIRM_DEVICE_CREDENTIAL_ERROR, args).sendToTarget();
-        }
-
-        @Override // Binder call
-        public void registerCancellationCallback(
-                IBiometricConfirmDeviceCredentialCallback callback) {
-            // TODO(b/123378871): Remove when moved.
-            // This callback replaces the one stored in the current session. If the session is null
-            // we can ignore this, since it means ConfirmDeviceCredential was launched by something
-            // else (not BiometricPrompt)
-            checkInternalPermission();
-
-            mHandler.obtainMessage(MSG_REGISTER_CANCELLATION_CALLBACK, callback).sendToTarget();
-        }
-
-        @Override // Binder call
         public void cancelAuthentication(IBinder token, String opPackageName)
                 throws RemoteException {
             checkPermission();
@@ -972,8 +847,8 @@
         // Cache the authenticators
         for (int featureId : FEATURE_ID) {
             if (hasFeature(featureId)) {
-                Authenticator authenticator =
-                        new Authenticator(featureId, getAuthenticator(featureId));
+                AuthenticatorWrapper authenticator =
+                        new AuthenticatorWrapper(featureId, getAuthenticator(featureId));
                 mAuthenticators.add(authenticator);
             }
         }
@@ -1011,7 +886,7 @@
 
         int modality = TYPE_NONE;
         int firstHwAvailable = TYPE_NONE;
-        for (Authenticator authenticatorWrapper : mAuthenticators) {
+        for (AuthenticatorWrapper authenticatorWrapper : mAuthenticators) {
             modality = authenticatorWrapper.getType();
             BiometricAuthenticator authenticator = authenticatorWrapper.getAuthenticator();
             if (authenticator.isHardwareDetected()) {
@@ -1108,7 +983,7 @@
     }
 
     private void logDialogDismissed(int reason) {
-        if (reason == BiometricPrompt.DISMISSED_REASON_CONFIRMED) {
+        if (reason == BiometricPrompt.DISMISSED_REASON_BIOMETRIC_CONFIRMED) {
             // Explicit auth, authentication confirmed.
             // Latency in this case is authenticated -> confirmed. <Biometric>Service
             // should have the first half (first acquired -> authenticated).
@@ -1254,49 +1129,6 @@
         }
     }
 
-    private void handleOnConfirmDeviceCredentialSuccess() {
-        if (mConfirmDeviceCredentialReceiver == null) {
-            Slog.w(TAG, "handleOnConfirmDeviceCredentialSuccess null!");
-            return;
-        }
-        try {
-            mConfirmDeviceCredentialReceiver.onAuthenticationSucceeded();
-            if (mCurrentAuthSession != null) {
-                mCurrentAuthSession = null;
-            }
-        } catch (RemoteException e) {
-            Slog.e(TAG, "RemoteException", e);
-        }
-        mConfirmDeviceCredentialReceiver = null;
-    }
-
-    private void handleOnConfirmDeviceCredentialError(int error, String message) {
-        if (mConfirmDeviceCredentialReceiver == null) {
-            Slog.w(TAG, "handleOnConfirmDeviceCredentialError null! Error: "
-                    + error + " " + message);
-            return;
-        }
-        try {
-            mConfirmDeviceCredentialReceiver.onError(error, message);
-            if (mCurrentAuthSession != null) {
-                mCurrentAuthSession = null;
-            }
-        } catch (RemoteException e) {
-            Slog.e(TAG, "RemoteException", e);
-        }
-        mConfirmDeviceCredentialReceiver = null;
-    }
-
-    private void handleRegisterCancellationCallback(
-            IBiometricConfirmDeviceCredentialCallback callback) {
-        if (mCurrentAuthSession == null) {
-            Slog.d(TAG, "Current auth session null");
-            return;
-        }
-        Slog.d(TAG, "Updating cancel callback");
-        mCurrentAuthSession.mConfirmDeviceCredentialCallback = callback;
-    }
-
     private void handleOnError(int cookie, int error, String message) {
         Slog.d(TAG, "handleOnError: " + error + " cookie: " + cookie);
         // Errors can either be from the current auth session or the pending auth session.
@@ -1307,34 +1139,34 @@
         // of their intended receivers.
         try {
             if (mCurrentAuthSession != null && mCurrentAuthSession.containsCookie(cookie)) {
-
                 mCurrentAuthSession.mErrorEscrow = error;
                 mCurrentAuthSession.mErrorStringEscrow = message;
 
-                if (mCurrentAuthSession.isFromConfirmDeviceCredential()) {
-                    // If we were invoked by ConfirmDeviceCredential, do not delete the current
-                    // auth session since we still need to respond to cancel signal while
-                    if (DEBUG) Slog.d(TAG, "From CDC, transition to CANCELED_SHOWING_CDC state");
-
-                    // Send the error to ConfirmDeviceCredential so that it goes to Pin/Pattern/Pass
-                    // screen
-                    mCurrentAuthSession.mClientReceiver.onError(error, message);
-                    mCurrentAuthSession.mState = STATE_BIOMETRIC_AUTH_CANCELED_SHOWING_CDC;
-                    mStatusBarService.hideBiometricDialog();
-                } else if (mCurrentAuthSession.mState == STATE_AUTH_STARTED) {
-                    mCurrentAuthSession.mState = STATE_ERROR_PENDING_SYSUI;
-                    if (error == BiometricConstants.BIOMETRIC_ERROR_CANCELED) {
-                        mStatusBarService.hideBiometricDialog();
+                if (mCurrentAuthSession.mState == STATE_AUTH_STARTED) {
+                    final boolean errorLockout = error == BiometricConstants.BIOMETRIC_ERROR_LOCKOUT
+                            || error == BiometricConstants.BIOMETRIC_ERROR_LOCKOUT_PERMANENT;
+                    if (mCurrentAuthSession.isAllowDeviceCredential() && errorLockout) {
+                        // SystemUI handles transition from biometric to device credential.
+                        mCurrentAuthSession.mState = STATE_SHOWING_DEVICE_CREDENTIAL;
+                        mStatusBarService.onBiometricError(error, message);
                     } else {
-                        mStatusBarService.onBiometricError(message);
+                        mCurrentAuthSession.mState = STATE_ERROR_PENDING_SYSUI;
+                        if (error == BiometricConstants.BIOMETRIC_ERROR_CANCELED) {
+                            mStatusBarService.hideAuthenticationDialog();
+                        } else {
+                            mStatusBarService.onBiometricError(error, message);
+                        }
                     }
                 } else if (mCurrentAuthSession.mState == STATE_AUTH_PAUSED) {
                     // In the "try again" state, we should forward canceled errors to
                     // the client and and clean up. The only error we should get here is
                     // ERROR_CANCELED due to another client kicking us out.
                     mCurrentAuthSession.mClientReceiver.onError(error, message);
-                    mStatusBarService.hideBiometricDialog();
+                    mStatusBarService.hideAuthenticationDialog();
                     mCurrentAuthSession = null;
+                } else if (mCurrentAuthSession.mState == STATE_SHOWING_DEVICE_CREDENTIAL) {
+                    Slog.d(TAG, "Biometric canceled, ignoring from state: "
+                            + mCurrentAuthSession.mState);
                 } else {
                     Slog.e(TAG, "Impossible session error state: "
                             + mCurrentAuthSession.mState);
@@ -1342,12 +1174,38 @@
             } else if (mPendingAuthSession != null
                     && mPendingAuthSession.containsCookie(cookie)) {
                 if (mPendingAuthSession.mState == STATE_AUTH_CALLED) {
-                    mPendingAuthSession.mClientReceiver.onError(error, message);
-                    mPendingAuthSession = null;
+                    // If any error is received while preparing the auth session (lockout, etc),
+                    // and if device credential is allowed, just show the credential UI.
+                    if (mPendingAuthSession.isAllowDeviceCredential()) {
+                        int authenticators = mPendingAuthSession.mBundle
+                                .getInt(BiometricPrompt.KEY_AUTHENTICATORS_ALLOWED, 0);
+                        // Disallow biometric and notify SystemUI to show the authentication prompt.
+                        authenticators &= ~Authenticator.TYPE_BIOMETRIC;
+                        mPendingAuthSession.mBundle.putInt(
+                                BiometricPrompt.KEY_AUTHENTICATORS_ALLOWED,
+                                authenticators);
+
+                        mCurrentAuthSession = mPendingAuthSession;
+                        mCurrentAuthSession.mState = STATE_SHOWING_DEVICE_CREDENTIAL;
+                        mPendingAuthSession = null;
+
+                        mStatusBarService.showAuthenticationDialog(
+                                mCurrentAuthSession.mBundle,
+                                mInternalReceiver,
+                                0 /* biometricModality */,
+                                false /* requireConfirmation */,
+                                mCurrentAuthSession.mUserId,
+                                mCurrentAuthSession.mOpPackageName);
+                    } else {
+                        mPendingAuthSession.mClientReceiver.onError(error, message);
+                        mPendingAuthSession = null;
+                    }
                 } else {
                     Slog.e(TAG, "Impossible pending session error state: "
                             + mPendingAuthSession.mState);
                 }
+            } else {
+                Slog.e(TAG, "Unknown cookie: " + cookie);
             }
         } catch (RemoteException e) {
             Slog.e(TAG, "Remote exception", e);
@@ -1385,9 +1243,12 @@
 
         try {
             switch (reason) {
-                case BiometricPrompt.DISMISSED_REASON_CONFIRMED:
-                case BiometricPrompt.DISMISSED_REASON_CONFIRM_NOT_REQUIRED:
-                    mKeyStore.addAuthToken(mCurrentAuthSession.mTokenEscrow);
+                case BiometricPrompt.DISMISSED_REASON_CREDENTIAL_CONFIRMED:
+                case BiometricPrompt.DISMISSED_REASON_BIOMETRIC_CONFIRMED:
+                case BiometricPrompt.DISMISSED_REASON_BIOMETRIC_CONFIRM_NOT_REQUIRED:
+                    if (mCurrentAuthSession.mTokenEscrow != null) {
+                        mKeyStore.addAuthToken(mCurrentAuthSession.mTokenEscrow);
+                    }
                     mCurrentAuthSession.mClientReceiver.onAuthenticationSucceeded();
                     break;
 
@@ -1439,12 +1300,37 @@
                 mCurrentAuthSession.mCallingUid,
                 mCurrentAuthSession.mCallingPid,
                 mCurrentAuthSession.mCallingUserId,
-                mCurrentAuthSession.mModality,
-                mCurrentAuthSession.mConfirmDeviceCredentialCallback);
+                mCurrentAuthSession.mModality);
     }
 
+    private void handleOnDeviceCredentialPressed() {
+        Slog.d(TAG, "onDeviceCredentialPressed");
+        if (mCurrentAuthSession == null) {
+            Slog.e(TAG, "Auth session null");
+            return;
+        }
+
+        // Cancel authentication. Skip the token/package check since we are cancelling
+        // from system server. The interface is permission protected so this is fine.
+        cancelInternal(null /* token */, null /* package */, false /* fromClient */);
+
+        mCurrentAuthSession.mState = STATE_SHOWING_DEVICE_CREDENTIAL;
+    }
+
+    /**
+     * Invoked when each service has notified that its client is ready to be started. When
+     * all biometrics are ready, this invokes the SystemUI dialog through StatusBar.
+     */
     private void handleOnReadyForAuthentication(int cookie, boolean requireConfirmation,
             int userId) {
+        if (mPendingAuthSession == null) {
+            // Only should happen if a biometric was locked out when authenticate() was invoked.
+            // In that case, if device credentials are allowed, the UI is already showing. If not
+            // allowed, the error has already been returned to the caller.
+            Slog.w(TAG, "Pending auth session null");
+            return;
+        }
+
         Iterator it = mPendingAuthSession.mModalitiesWaiting.entrySet().iterator();
         while (it.hasNext()) {
             Map.Entry<Integer, Integer> pair = (Map.Entry) it.next();
@@ -1486,7 +1372,7 @@
                 }
 
                 if (!continuing) {
-                    mStatusBarService.showBiometricDialog(mCurrentAuthSession.mBundle,
+                    mStatusBarService.showAuthenticationDialog(mCurrentAuthSession.mBundle,
                             mInternalReceiver, modality, requireConfirmation, userId,
                             mCurrentAuthSession.mOpPackageName);
                 }
@@ -1498,16 +1384,21 @@
 
     private void handleAuthenticate(IBinder token, long sessionId, int userId,
             IBiometricServiceReceiver receiver, String opPackageName, Bundle bundle,
-            int callingUid, int callingPid, int callingUserId,
-            IBiometricConfirmDeviceCredentialCallback callback) {
+            int callingUid, int callingPid, int callingUserId) {
 
         mHandler.post(() -> {
             final Pair<Integer, Integer> result = checkAndGetBiometricModality(userId);
             final int modality = result.first;
             final int error = result.second;
 
-            // Check for errors, notify callback, and return
-            if (error != BiometricConstants.BIOMETRIC_SUCCESS) {
+            final boolean credentialAllowed = Utils.isDeviceCredentialAllowed(bundle);
+
+            if (error != BiometricConstants.BIOMETRIC_SUCCESS && credentialAllowed) {
+                // If there's a problem but device credential is allowed, only show credential UI.
+                bundle.putInt(BiometricPrompt.KEY_AUTHENTICATORS_ALLOWED,
+                        Authenticator.TYPE_CREDENTIAL);
+            } else if (error != BiometricConstants.BIOMETRIC_SUCCESS) {
+                // Check for errors, notify callback, and return
                 try {
                     final String hardwareUnavailable =
                             getContext().getString(R.string.biometric_error_hw_unavailable);
@@ -1535,7 +1426,7 @@
             // Start preparing for authentication. Authentication starts when
             // all modalities requested have invoked onReadyForAuthentication.
             authenticateInternal(token, sessionId, userId, receiver, opPackageName, bundle,
-                    callingUid, callingPid, callingUserId, modality, callback);
+                    callingUid, callingPid, callingUserId, modality);
         });
     }
 
@@ -1550,8 +1441,7 @@
      */
     private void authenticateInternal(IBinder token, long sessionId, int userId,
             IBiometricServiceReceiver receiver, String opPackageName, Bundle bundle,
-            int callingUid, int callingPid, int callingUserId, int modality,
-            IBiometricConfirmDeviceCredentialCallback callback) {
+            int callingUid, int callingPid, int callingUserId, int modality) {
         try {
             boolean requireConfirmation = bundle.getBoolean(
                     BiometricPrompt.KEY_REQUIRE_CONFIRMATION, true /* default */);
@@ -1565,27 +1455,49 @@
             // with the cookie. Once all cookies are received, we can show the prompt
             // and let the services start authenticating. The cookie should be non-zero.
             final int cookie = mRandom.nextInt(Integer.MAX_VALUE - 1) + 1;
+            final int authenticators = bundle.getInt(BiometricPrompt.KEY_AUTHENTICATORS_ALLOWED);
             Slog.d(TAG, "Creating auth session. Modality: " + modality
-                    + ", cookie: " + cookie);
-            final HashMap<Integer, Integer> authenticators = new HashMap<>();
-            authenticators.put(modality, cookie);
-            mPendingAuthSession = new AuthSession(authenticators, token, sessionId, userId,
+                    + ", cookie: " + cookie
+                    + ", authenticators: " + authenticators);
+            final HashMap<Integer, Integer> modalities = new HashMap<>();
+
+            // If it's only device credential, we don't need to wait - LockSettingsService is
+            // always ready to check credential (SystemUI invokes that path).
+            if ((authenticators & ~Authenticator.TYPE_CREDENTIAL) != 0) {
+                modalities.put(modality, cookie);
+            }
+            mPendingAuthSession = new AuthSession(modalities, token, sessionId, userId,
                     receiver, opPackageName, bundle, callingUid, callingPid, callingUserId,
-                    modality, requireConfirmation, callback);
-            mPendingAuthSession.mState = STATE_AUTH_CALLED;
-            // No polymorphism :(
-            if ((modality & TYPE_FINGERPRINT) != 0) {
-                mFingerprintService.prepareForAuthentication(token, sessionId, userId,
-                        mInternalReceiver, opPackageName, cookie,
-                        callingUid, callingPid, callingUserId);
-            }
-            if ((modality & TYPE_IRIS) != 0) {
-                Slog.w(TAG, "Iris unsupported");
-            }
-            if ((modality & TYPE_FACE) != 0) {
-                mFaceService.prepareForAuthentication(requireConfirmation,
-                        token, sessionId, userId, mInternalReceiver, opPackageName,
-                        cookie, callingUid, callingPid, callingUserId);
+                    modality, requireConfirmation);
+
+            if (authenticators == Authenticator.TYPE_CREDENTIAL) {
+                mPendingAuthSession.mState = STATE_SHOWING_DEVICE_CREDENTIAL;
+                mCurrentAuthSession = mPendingAuthSession;
+                mPendingAuthSession = null;
+
+                mStatusBarService.showAuthenticationDialog(
+                        mCurrentAuthSession.mBundle,
+                        mInternalReceiver,
+                        0 /* biometricModality */,
+                        false /* requireConfirmation */,
+                        mCurrentAuthSession.mUserId,
+                        mCurrentAuthSession.mOpPackageName);
+            } else {
+                mPendingAuthSession.mState = STATE_AUTH_CALLED;
+                // No polymorphism :(
+                if ((modality & TYPE_FINGERPRINT) != 0) {
+                    mFingerprintService.prepareForAuthentication(token, sessionId, userId,
+                            mInternalReceiver, opPackageName, cookie,
+                            callingUid, callingPid, callingUserId);
+                }
+                if ((modality & TYPE_IRIS) != 0) {
+                    Slog.w(TAG, "Iris unsupported");
+                }
+                if ((modality & TYPE_FACE) != 0) {
+                    mFaceService.prepareForAuthentication(requireConfirmation,
+                            token, sessionId, userId, mInternalReceiver, opPackageName,
+                            cookie, callingUid, callingPid, callingUserId);
+                }
             }
         } catch (RemoteException e) {
             Slog.e(TAG, "Unable to start authentication", e);
@@ -1598,20 +1510,7 @@
             return;
         }
 
-        if (mCurrentAuthSession != null
-                && mCurrentAuthSession.mState == STATE_BIOMETRIC_AUTH_CANCELED_SHOWING_CDC) {
-            if (DEBUG) Slog.d(TAG, "Cancel received while ConfirmDeviceCredential showing");
-            try {
-                mCurrentAuthSession.mConfirmDeviceCredentialCallback.cancel();
-            } catch (RemoteException e) {
-                Slog.e(TAG, "Unable to cancel ConfirmDeviceCredential", e);
-            }
-
-            // TODO(b/123378871): Remove when moved. Piggy back on this for now to clean up.
-            handleOnConfirmDeviceCredentialError(BiometricConstants.BIOMETRIC_ERROR_CANCELED,
-                    getContext().getString(R.string.biometric_error_canceled));
-        } else if (mCurrentAuthSession != null
-                && mCurrentAuthSession.mState != STATE_AUTH_STARTED) {
+        if (mCurrentAuthSession != null && mCurrentAuthSession.mState != STATE_AUTH_STARTED) {
             // We need to check the current authenticators state. If we're pending confirm
             // or idle, we need to dismiss the dialog and send an ERROR_CANCELED to the client,
             // since we won't be getting an onError from the driver.
@@ -1624,24 +1523,12 @@
                 );
 
                 mCurrentAuthSession = null;
-                mStatusBarService.hideBiometricDialog();
+                mStatusBarService.hideAuthenticationDialog();
             } catch (RemoteException e) {
                 Slog.e(TAG, "Remote exception", e);
             }
         } else {
-            boolean fromCDC = false;
-            if (mCurrentAuthSession != null) {
-                fromCDC = mCurrentAuthSession.mBundle.getBoolean(
-                        BiometricPrompt.KEY_FROM_CONFIRM_DEVICE_CREDENTIAL, false);
-            }
-
-            if (fromCDC) {
-                if (DEBUG) Slog.d(TAG, "Cancelling from CDC");
-                cancelInternal(token, opPackageName, false /* fromClient */);
-            } else {
-                cancelInternal(token, opPackageName, true /* fromClient */);
-            }
-
+            cancelInternal(token, opPackageName, true /* fromClient */);
         }
     }
 
diff --git a/services/core/java/com/android/server/biometrics/Utils.java b/services/core/java/com/android/server/biometrics/Utils.java
index 4fa29ac..ed5f9de 100644
--- a/services/core/java/com/android/server/biometrics/Utils.java
+++ b/services/core/java/com/android/server/biometrics/Utils.java
@@ -17,10 +17,15 @@
 package com.android.server.biometrics;
 
 import android.content.Context;
+import android.hardware.biometrics.Authenticator;
+import android.hardware.biometrics.BiometricPrompt;
 import android.os.Build;
+import android.os.Bundle;
 import android.os.UserHandle;
 import android.provider.Settings;
 
+import com.android.internal.annotations.VisibleForTesting;
+
 public class Utils {
     public static boolean isDebugEnabled(Context context, int targetUserId) {
         if (targetUserId == UserHandle.USER_NULL) {
@@ -38,4 +43,43 @@
         }
         return true;
     }
+
+    /**
+     * Combine {@link BiometricPrompt#KEY_ALLOW_DEVICE_CREDENTIAL} with
+     * {@link BiometricPrompt#KEY_AUTHENTICATORS_ALLOWED}, as the former is not flexible
+     * enough.
+     */
+    public static void combineAuthenticatorBundles(Bundle bundle) {
+        boolean biometricEnabled = true; // enabled by default
+        boolean credentialEnabled = bundle.getBoolean(
+                BiometricPrompt.KEY_ALLOW_DEVICE_CREDENTIAL, false);
+        if (bundle.get(BiometricPrompt.KEY_AUTHENTICATORS_ALLOWED) != null) {
+            final int authenticatorFlags =
+                    bundle.getInt(BiometricPrompt.KEY_AUTHENTICATORS_ALLOWED);
+            biometricEnabled = (authenticatorFlags & Authenticator.TYPE_BIOMETRIC) != 0;
+            // Using both KEY_ALLOW_DEVICE_CREDENTIAL and KEY_AUTHENTICATORS_ALLOWED together
+            // is not supported. Default to overwriting.
+            credentialEnabled = (authenticatorFlags & Authenticator.TYPE_CREDENTIAL) != 0;
+        }
+
+        bundle.remove(BiometricPrompt.KEY_ALLOW_DEVICE_CREDENTIAL);
+
+        int authenticators = 0;
+        if (biometricEnabled) {
+            authenticators |= Authenticator.TYPE_BIOMETRIC;
+        }
+        if (credentialEnabled) {
+            authenticators |= Authenticator.TYPE_CREDENTIAL;
+        }
+        bundle.putInt(BiometricPrompt.KEY_AUTHENTICATORS_ALLOWED, authenticators);
+    }
+
+    /**
+     * @param bundle should be first processed by {@link #combineAuthenticatorBundles(Bundle)}
+     * @return true if device credential allowed.
+     */
+    public static boolean isDeviceCredentialAllowed(Bundle bundle) {
+        final int authenticators = bundle.getInt(BiometricPrompt.KEY_AUTHENTICATORS_ALLOWED);
+        return (authenticators & Authenticator.TYPE_CREDENTIAL) != 0;
+    }
 }
diff --git a/services/core/java/com/android/server/biometrics/face/FaceService.java b/services/core/java/com/android/server/biometrics/face/FaceService.java
index 9eb0d50..1b13212 100644
--- a/services/core/java/com/android/server/biometrics/face/FaceService.java
+++ b/services/core/java/com/android/server/biometrics/face/FaceService.java
@@ -1089,7 +1089,7 @@
         publishBinderService(Context.FACE_SERVICE, new FaceServiceWrapper());
         // Get the face daemon on FaceService's on thread so SystemServerInitThreadPool isn't
         // blocked
-        SystemServerInitThreadPool.get().submit(() -> mHandler.post(this::getFaceDaemon),
+        SystemServerInitThreadPool.submit(() -> mHandler.post(this::getFaceDaemon),
                 TAG + ".onStart");
     }
 
diff --git a/services/core/java/com/android/server/biometrics/fingerprint/FingerprintService.java b/services/core/java/com/android/server/biometrics/fingerprint/FingerprintService.java
index 320e102..d85af2e 100644
--- a/services/core/java/com/android/server/biometrics/fingerprint/FingerprintService.java
+++ b/services/core/java/com/android/server/biometrics/fingerprint/FingerprintService.java
@@ -725,7 +725,7 @@
     public void onStart() {
         super.onStart();
         publishBinderService(Context.FINGERPRINT_SERVICE, new FingerprintServiceWrapper());
-        SystemServerInitThreadPool.get().submit(this::getFingerprintDaemon, TAG + ".onStart");
+        SystemServerInitThreadPool.submit(this::getFingerprintDaemon, TAG + ".onStart");
     }
 
     @Override
diff --git a/services/core/java/com/android/server/compat/CompatConfig.java b/services/core/java/com/android/server/compat/CompatConfig.java
index 027e2fb..0fabd9a 100644
--- a/services/core/java/com/android/server/compat/CompatConfig.java
+++ b/services/core/java/com/android/server/compat/CompatConfig.java
@@ -25,6 +25,7 @@
 
 import com.android.internal.annotations.GuardedBy;
 import com.android.internal.annotations.VisibleForTesting;
+import com.android.internal.compat.CompatibilityChangeConfig;
 import com.android.server.compat.config.Change;
 import com.android.server.compat.config.XmlParser;
 
@@ -186,6 +187,43 @@
         }
         return overrideExists;
     }
+    /**
+     * Overrides the enabled state for a given change and app. This method is intended to be used
+     * *only* for debugging purposes.
+     *
+     * <p>Note, package overrides are not persistent and will be lost on system or runtime restart.
+     *
+     * @param overrides list of overrides to default changes config.
+     * @param packageName app for which the overrides will be applied.
+     */
+    public void addOverrides(
+            CompatibilityChangeConfig overrides, String packageName) {
+        synchronized (mChanges) {
+            for (Long changeId: overrides.enabledChanges()) {
+                addOverride(changeId, packageName, true);
+            }
+            for (Long changeId: overrides.disabledChanges()) {
+                addOverride(changeId, packageName, false);
+            }
+        }
+    }
+
+    /**
+     * Removes all overrides previously added via {@link #addOverride(long, String, boolean)} or
+     * {@link #addAppOverrides(CompatibilityChangeConfig, String)} for a certain package.
+     *
+     * <p>This restores the default behaviour for the given change and app, once any app
+     * processes have been restarted.
+     *
+     * @param packageName The package for which the overrides should be purged.
+     */
+    public void removePackageOverrides(String packageName) {
+        synchronized (mChanges) {
+            for (int i = 0; i < mChanges.size(); ++i) {
+                mChanges.valueAt(i).removePackageOverride(packageName);
+            }
+        }
+    }
 
     /**
     * Dumps the current list of compatibility config information.
diff --git a/services/core/java/com/android/server/compat/OWNERS b/services/core/java/com/android/server/compat/OWNERS
new file mode 100644
index 0000000..2b7cdb0
--- /dev/null
+++ b/services/core/java/com/android/server/compat/OWNERS
@@ -0,0 +1,7 @@
+# Use this reviewer by default.
+platform-compat-eng+reviews@google.com
+
+andreionea@google.com
+atrost@google.com
+mathewi@google.com
+satayev@google.com
diff --git a/services/core/java/com/android/server/compat/PlatformCompat.java b/services/core/java/com/android/server/compat/PlatformCompat.java
index 8e09d0e..8a7dcc1 100644
--- a/services/core/java/com/android/server/compat/PlatformCompat.java
+++ b/services/core/java/com/android/server/compat/PlatformCompat.java
@@ -23,6 +23,7 @@
 import android.util.StatsLog;
 
 import com.android.internal.compat.ChangeReporter;
+import com.android.internal.compat.CompatibilityChangeConfig;
 import com.android.internal.compat.IPlatformCompat;
 import com.android.internal.util.DumpUtils;
 
@@ -47,7 +48,8 @@
 
     @Override
     public void reportChange(long changeId, ApplicationInfo appInfo) {
-        reportChange(changeId, appInfo, StatsLog.APP_COMPATIBILITY_CHANGE_REPORTED__STATE__LOGGED);
+        reportChange(changeId, appInfo.uid,
+                StatsLog.APP_COMPATIBILITY_CHANGE_REPORTED__STATE__LOGGED);
     }
 
     @Override
@@ -60,13 +62,18 @@
     }
 
     @Override
+    public void reportChangeByUid(long changeId, int uid) {
+        reportChange(changeId, uid, StatsLog.APP_COMPATIBILITY_CHANGE_REPORTED__STATE__LOGGED);
+    }
+
+    @Override
     public boolean isChangeEnabled(long changeId, ApplicationInfo appInfo) {
         if (CompatConfig.get().isChangeEnabled(changeId, appInfo)) {
-            reportChange(changeId, appInfo,
+            reportChange(changeId, appInfo.uid,
                     StatsLog.APP_COMPATIBILITY_CHANGE_REPORTED__STATE__ENABLED);
             return true;
         }
-        reportChange(changeId, appInfo,
+        reportChange(changeId, appInfo.uid,
                 StatsLog.APP_COMPATIBILITY_CHANGE_REPORTED__STATE__DISABLED);
         return false;
     }
@@ -81,11 +88,44 @@
     }
 
     @Override
+    public boolean isChangeEnabledByUid(long changeId, int uid) {
+        String[] packages = mContext.getPackageManager().getPackagesForUid(uid);
+        if (packages == null || packages.length == 0) {
+            return true;
+        }
+        boolean enabled = true;
+        for (String packageName : packages) {
+            enabled = enabled && isChangeEnabledByPackageName(changeId, packageName);
+        }
+        return enabled;
+    }
+
+    @Override
+    public void setOverrides(CompatibilityChangeConfig overrides, String packageName) {
+        CompatConfig.get().addOverrides(overrides, packageName);
+    }
+
+    @Override
+    public void clearOverrides(String packageName) {
+        CompatConfig config = CompatConfig.get();
+        config.removePackageOverrides(packageName);
+    }
+
+    @Override
     protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
         if (!DumpUtils.checkDumpAndUsageStatsPermission(mContext, "platform_compat", pw)) return;
         CompatConfig.get().dumpConfig(pw);
     }
 
+    /**
+     * Clears information stored about events reported on behalf of an app.
+     * To be called once upon app start or end. A second call would be a no-op.
+     * @param appInfo the app to reset
+     */
+    public void resetReporting(ApplicationInfo appInfo) {
+        mChangeReporter.resetReportedChanges(appInfo.uid);
+    }
+
     private ApplicationInfo getApplicationInfo(String packageName) {
         try {
             return mContext.getPackageManager().getApplicationInfo(packageName, 0);
@@ -95,8 +135,7 @@
         return null;
     }
 
-    private void reportChange(long changeId, ApplicationInfo appInfo, int state) {
-        int uid = appInfo.uid;
+    private void reportChange(long changeId, int uid, int state) {
         mChangeReporter.reportChange(uid, changeId, state);
     }
 }
diff --git a/services/core/java/com/android/server/display/ColorFade.java b/services/core/java/com/android/server/display/ColorFade.java
index c46fc20..29026e8 100644
--- a/services/core/java/com/android/server/display/ColorFade.java
+++ b/services/core/java/com/android/server/display/ColorFade.java
@@ -114,6 +114,8 @@
     private final FloatBuffer mVertexBuffer = createNativeFloatBuffer(8);
     private final FloatBuffer mTexCoordBuffer = createNativeFloatBuffer(8);
 
+    private final Transaction mTransaction = new Transaction();
+
     /**
      * Animates an color fade warming up.
      */
@@ -659,14 +661,10 @@
 
     private boolean showSurface(float alpha) {
         if (!mSurfaceVisible || mSurfaceAlpha != alpha) {
-            SurfaceControl.openTransaction();
-            try {
-                mSurfaceControl.setLayer(COLOR_FADE_LAYER);
-                mSurfaceControl.setAlpha(alpha);
-                mSurfaceControl.show();
-            } finally {
-                SurfaceControl.closeTransaction();
-            }
+            mTransaction.setLayer(mSurfaceControl, COLOR_FADE_LAYER)
+                    .setAlpha(mSurfaceControl, alpha)
+                    .show(mSurfaceControl)
+                    .apply();
             mSurfaceVisible = true;
             mSurfaceAlpha = alpha;
         }
diff --git a/services/core/java/com/android/server/hdmi/HdmiCecLocalDeviceAudioSystem.java b/services/core/java/com/android/server/hdmi/HdmiCecLocalDeviceAudioSystem.java
index 4f4baab..61d4d4b 100644
--- a/services/core/java/com/android/server/hdmi/HdmiCecLocalDeviceAudioSystem.java
+++ b/services/core/java/com/android/server/hdmi/HdmiCecLocalDeviceAudioSystem.java
@@ -850,36 +850,25 @@
                         mAddress, Constants.ADDR_BROADCAST, systemAudioStatusOn));
 
         if (systemAudioStatusOn) {
+            // If TV sends out SAM Request with a path of a non-CEC device, which should not show
+            // up in the CEC device list and not under the current AVR device, the AVR would switch
+            // to ARC.
             int sourcePhysicalAddress = HdmiUtils.twoBytesToInt(message.getParams());
-            if (sourcePhysicalAddress != getActiveSource().physicalAddress) {
-                // If the Active Source recorded by the current device is not synced up with TV,
-                // update the Active Source internally.
-                if (sourcePhysicalAddress == mService.getPhysicalAddress()) {
-                    // If the active path is the current device itself, update with local info
-                    if (mService.playback() != null) {
-                        setActiveSource(mService.playback().mAddress, sourcePhysicalAddress);
-                    } else {
-                        setActiveSource(mAddress, sourcePhysicalAddress);
-                    }
-                } else {
-                    // If it's not the current device, look for the device info from the list
-                    for (HdmiDeviceInfo info : HdmiUtils.sparseArrayToList(mDeviceInfos)) {
-                        if (info.getPhysicalAddress() == sourcePhysicalAddress) {
-                            setActiveSource(info.getLogicalAddress(), info.getPhysicalAddress());
-                            break;
-                        }
-                    }
-                }
-                // If the Active path from TV's System Audio Mode request does not belong to any
-                // device in the local device list, record the new Active physicalAddress with an
-                // unregistered logical address first. Then query the Active Source again.
-                if (sourcePhysicalAddress != getActiveSource().physicalAddress) {
-                    setActiveSource(Constants.ADDR_UNREGISTERED, sourcePhysicalAddress);
-                    mService.sendCecCommand(
-                        HdmiCecMessageBuilder.buildRequestActiveSource(mAddress));
+            if (HdmiUtils.getLocalPortFromPhysicalAddress(
+                    sourcePhysicalAddress, getDeviceInfo().getPhysicalAddress())
+                            != HdmiUtils.TARGET_NOT_UNDER_LOCAL_DEVICE) {
+                return true;
+            }
+            boolean isDeviceInCecDeviceList = false;
+            for (HdmiDeviceInfo info : HdmiUtils.sparseArrayToList(mDeviceInfos)) {
+                if (info.getPhysicalAddress() == sourcePhysicalAddress) {
+                    isDeviceInCecDeviceList = true;
+                    break;
                 }
             }
-            switchInputOnReceivingNewActivePath(sourcePhysicalAddress);
+            if (!isDeviceInCecDeviceList) {
+                switchInputOnReceivingNewActivePath(sourcePhysicalAddress);
+            }
         }
         return true;
     }
diff --git a/services/core/java/com/android/server/hdmi/HdmiControlService.java b/services/core/java/com/android/server/hdmi/HdmiControlService.java
index c3354e1..1794df3 100644
--- a/services/core/java/com/android/server/hdmi/HdmiControlService.java
+++ b/services/core/java/com/android/server/hdmi/HdmiControlService.java
@@ -311,6 +311,11 @@
     private IHdmiControlCallback mDisplayStatusCallback = null;
 
     @Nullable
+    // Save callback when the device is still under logcial address allocation
+    // Invoke once new local device is ready.
+    private IHdmiControlCallback mOtpCallbackPendingAddressAllocation = null;
+
+    @Nullable
     private HdmiCecController mCecController;
 
     // HDMI port information. Stored in the unmodifiable list to keep the static information
@@ -785,17 +790,21 @@
                     // Address allocation completed for all devices. Notify each device.
                     if (allocatingDevices.size() == ++finished[0]) {
                         mAddressAllocated = true;
-                        // Reinvoke the saved display status callback once the local device is ready.
-                        if (mDisplayStatusCallback != null) {
-                            queryDisplayStatus(mDisplayStatusCallback);
-                            mDisplayStatusCallback = null;
-                        }
                         if (initiatedBy != INITIATED_BY_HOTPLUG) {
                             // In case of the hotplug we don't call onInitializeCecComplete()
                             // since we reallocate the logical address only.
                             onInitializeCecComplete(initiatedBy);
                         }
                         notifyAddressAllocated(allocatedDevices, initiatedBy);
+                        // Reinvoke the saved display status callback once the local device is ready.
+                        if (mDisplayStatusCallback != null) {
+                            queryDisplayStatus(mDisplayStatusCallback);
+                            mDisplayStatusCallback = null;
+                        }
+                        if (mOtpCallbackPendingAddressAllocation != null) {
+                            oneTouchPlay(mOtpCallbackPendingAddressAllocation);
+                            mOtpCallbackPendingAddressAllocation = null;
+                        }
                         mCecMessageBuffer.processMessages();
                     }
                 }
@@ -2246,8 +2255,16 @@
     }
 
     @ServiceThreadOnly
-    private void oneTouchPlay(final IHdmiControlCallback callback) {
+    @VisibleForTesting
+    protected void oneTouchPlay(final IHdmiControlCallback callback) {
         assertRunOnServiceThread();
+        if (!mAddressAllocated) {
+            mOtpCallbackPendingAddressAllocation = callback;
+            Slog.d(TAG, "Local device is under address allocation. "
+                        + "Save OTP callback for later process.");
+            return;
+        }
+
         HdmiCecLocalDeviceSource source = playback();
         if (source == null) {
             source = audioSystem();
diff --git a/services/core/java/com/android/server/hdmi/OneTouchPlayAction.java b/services/core/java/com/android/server/hdmi/OneTouchPlayAction.java
index c8fc5fc..4962af1 100644
--- a/services/core/java/com/android/server/hdmi/OneTouchPlayAction.java
+++ b/services/core/java/com/android/server/hdmi/OneTouchPlayAction.java
@@ -77,7 +77,6 @@
         sendCommand(HdmiCecMessageBuilder.buildTextViewOn(getSourceAddress(), mTargetAddress));
         broadcastActiveSource();
         queryDevicePowerStatus();
-        mState = STATE_WAITING_FOR_REPORT_POWER_STATUS;
         addTimer(mState, HdmiConfig.TIMEOUT_MS);
         return true;
     }
@@ -99,6 +98,7 @@
     }
 
     private void queryDevicePowerStatus() {
+        mState = STATE_WAITING_FOR_REPORT_POWER_STATUS;
         sendCommand(HdmiCecMessageBuilder.buildGiveDevicePowerStatus(getSourceAddress(),
                 mTargetAddress));
     }
diff --git a/services/core/java/com/android/server/input/InputManagerService.java b/services/core/java/com/android/server/input/InputManagerService.java
index 7e6e668..f1af73a 100644
--- a/services/core/java/com/android/server/input/InputManagerService.java
+++ b/services/core/java/com/android/server/input/InputManagerService.java
@@ -71,7 +71,6 @@
 import android.view.IInputFilter;
 import android.view.IInputFilterHost;
 import android.view.IInputMonitorHost;
-import android.view.IWindow;
 import android.view.InputApplicationHandle;
 import android.view.InputChannel;
 import android.view.InputDevice;
@@ -186,9 +185,6 @@
     IInputFilter mInputFilter; // guarded by mInputFilterLock
     InputFilterHost mInputFilterHost; // guarded by mInputFilterLock
 
-    private IWindow mFocusedWindow;
-    private boolean mFocusedWindowHasCapture;
-
     private static native long nativeInit(InputManagerService service,
             Context context, MessageQueue messageQueue);
     private static native void nativeStart(long ptr);
@@ -544,20 +540,16 @@
     }
 
     /**
-     * Registers an input channel so that it can be used as an input event target.
+     * Registers an input channel so that it can be used as an input event target. The channel is
+     * registered with a generated token.
+     *
      * @param inputChannel The input channel to register.
-     * @param inputWindowHandle The handle of the input window associated with the
-     * input channel, or null if none.
      */
-    public void registerInputChannel(InputChannel inputChannel, IBinder token) {
+    public void registerInputChannel(InputChannel inputChannel) {
         if (inputChannel == null) {
             throw new IllegalArgumentException("inputChannel must not be null.");
         }
-
-        if (token == null) {
-            token = new Binder();
-        }
-        inputChannel.setToken(token);
+        inputChannel.setToken(new Binder());
 
         nativeRegisterInputChannel(mPtr, inputChannel, Display.INVALID_DISPLAY);
     }
@@ -1513,26 +1505,9 @@
 
     @Override
     public void requestPointerCapture(IBinder windowToken, boolean enabled) {
-        if (mFocusedWindow == null || mFocusedWindow.asBinder() != windowToken) {
-            Slog.e(TAG, "requestPointerCapture called for a window that has no focus: "
-                    + windowToken);
-            return;
-        }
-        if (mFocusedWindowHasCapture == enabled) {
-            Slog.i(TAG, "requestPointerCapture: already " + (enabled ? "enabled" : "disabled"));
-            return;
-        }
-        setPointerCapture(enabled);
-    }
-
-    private void setPointerCapture(boolean enabled) {
-        if (mFocusedWindowHasCapture != enabled) {
-            mFocusedWindowHasCapture = enabled;
-            try {
-                mFocusedWindow.dispatchPointerCaptureChanged(enabled);
-            } catch (RemoteException ex) {
-                /* ignore */
-            }
+        boolean requestConfigurationRefresh =
+                mWindowManagerCallbacks.requestPointerCapture(windowToken, enabled);
+        if (requestConfigurationRefresh) {
             nativeSetPointerCapture(mPtr, enabled);
         }
     }
@@ -1829,16 +1804,11 @@
 
     // Native callback
     private void notifyFocusChanged(IBinder oldToken, IBinder newToken) {
-        if (mFocusedWindow != null) {
-            if (mFocusedWindow.asBinder() == newToken) {
-                Slog.w(TAG, "notifyFocusChanged called with unchanged mFocusedWindow="
-                        + mFocusedWindow);
-                return;
-            }
-            setPointerCapture(false);
+        final boolean requestConfigurationRefresh =
+                mWindowManagerCallbacks.notifyFocusChanged(oldToken, newToken);
+        if (requestConfigurationRefresh) {
+            nativeSetPointerCapture(mPtr, false);
         }
-
-        mFocusedWindow = IWindow.Stub.asInterface(newToken);
     }
 
     // Native callback.
@@ -2116,6 +2086,20 @@
          * @param touchedToken The token for the window that received the input event.
          */
         void onPointerDownOutsideFocus(IBinder touchedToken);
+
+        /**
+         * Called when the focused window has changed.
+         *
+         * @return true if we want to request a configuration refresh.
+         */
+        boolean notifyFocusChanged(IBinder oldToken, IBinder newToken);
+
+        /**
+         * Called by the client to request pointer capture.
+         *
+         * @return true if we want to request a configuration refresh.
+         */
+        boolean requestPointerCapture(IBinder windowToken, boolean enabled);
     }
 
     /**
diff --git a/services/core/java/com/android/server/inputmethod/InputMethodManagerService.java b/services/core/java/com/android/server/inputmethod/InputMethodManagerService.java
index f20003a..b7fcd3f 100644
--- a/services/core/java/com/android/server/inputmethod/InputMethodManagerService.java
+++ b/services/core/java/com/android/server/inputmethod/InputMethodManagerService.java
@@ -3569,9 +3569,15 @@
             if (!calledWithValidTokenLocked(token)) {
                 return;
             }
-            if (mCurClient != null && mCurClient.client != null) {
-                executeOrSendMessage(mCurClient.client, mCaller.obtainMessageIO(
-                        MSG_APPLY_IME_VISIBILITY, setVisible ? 1 : 0, mCurClient));
+            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));
+                }
+            } else {
+                // Send to window manager to show IME after IME layout finishes.
+                mWindowManagerInternal.showImePostLayout(mLastImeTargetWindow);
             }
         }
     }
diff --git a/services/core/java/com/android/server/integrity/TEST_MAPPING b/services/core/java/com/android/server/integrity/TEST_MAPPING
new file mode 100644
index 0000000..b45b4ea
--- /dev/null
+++ b/services/core/java/com/android/server/integrity/TEST_MAPPING
@@ -0,0 +1,18 @@
+{
+  "presubmit": [
+    {
+      "name": "FrameworksServicesTests",
+      "options": [
+        {
+          "include-filter": "com.android.server.integrity."
+        },
+        {
+          "include-annotation": "android.platform.test.annotations.Presubmit"
+        },
+        {
+          "exclude-annotation": "androidx.test.filters.FlakyTest"
+        }
+      ]
+    }
+  ]
+}
diff --git a/services/core/java/com/android/server/integrity/engine/AppInstallMetadata.java b/services/core/java/com/android/server/integrity/engine/AppInstallMetadata.java
deleted file mode 100644
index c2ed3df..0000000
--- a/services/core/java/com/android/server/integrity/engine/AppInstallMetadata.java
+++ /dev/null
@@ -1,44 +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.server.integrity.engine;
-
-/**
- * The app install metadata.
- *
- * <p>The integrity component retrieves metadata for app installs from package manager, passing it
- * to the rule evaluation engine to evaluate the metadata against the rules.
- */
-public final class AppInstallMetadata {
-    final String mPackageName;
-    // Raw string encoding for the SHA-256 hash of the certificate of the app.
-    final String mAppCertificate;
-    final String mInstallerName;
-    // Raw string encoding for the SHA-256 hash of the certificate of the installer.
-    final String mInstallerCertificate;
-    final int mVersionCode;
-    final boolean mIsPreInstalled;
-
-    AppInstallMetadata(String packageName, String appCertificate, String installerName,
-            String installerCertificate, int versionCode, boolean isPreInstalled) {
-        this.mPackageName = packageName;
-        this.mAppCertificate = appCertificate;
-        this.mInstallerName = installerName;
-        this.mInstallerCertificate = installerCertificate;
-        this.mVersionCode = versionCode;
-        this.mIsPreInstalled = isPreInstalled;
-    }
-}
diff --git a/services/core/java/com/android/server/integrity/engine/RuleEvaluation.java b/services/core/java/com/android/server/integrity/engine/RuleEvaluation.java
deleted file mode 100644
index 93c9ada..0000000
--- a/services/core/java/com/android/server/integrity/engine/RuleEvaluation.java
+++ /dev/null
@@ -1,29 +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.server.integrity.engine;
-
-/**
- * The engine used to evaluate rules against app installs.
- *
- * <p>Every app install is evaluated against rules (pushed by the verifier) by the evaluation engine
- * to allow/block that install.
- */
-public final class RuleEvaluation {
-    private static final String TAG = "RuleEvaluation";
-
-    // TODO: Add singleton injection.
-}
diff --git a/services/core/java/com/android/server/integrity/engine/RuleEvaluationEngine.java b/services/core/java/com/android/server/integrity/engine/RuleEvaluationEngine.java
new file mode 100644
index 0000000..e90612e
--- /dev/null
+++ b/services/core/java/com/android/server/integrity/engine/RuleEvaluationEngine.java
@@ -0,0 +1,79 @@
+/*
+ * 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.integrity.engine;
+
+import android.util.Slog;
+
+import com.android.server.integrity.model.AppInstallMetadata;
+import com.android.server.integrity.model.IntegrityCheckResult;
+import com.android.server.integrity.model.Rule;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * The engine used to evaluate rules against app installs.
+ *
+ * <p>Every app install is evaluated against rules (pushed by the verifier) by the evaluation
+ * engine to allow/block that install.
+ */
+public final class RuleEvaluationEngine {
+    private static final String TAG = "RuleEvaluation";
+
+    // The engine for loading rules, retrieving metadata for app installs, and evaluating app
+    // installs against rules.
+    private static RuleEvaluationEngine sRuleEvaluationEngine;
+
+    /**
+     * Provide a singleton instance of the rule evaluation engine.
+     */
+    public static synchronized RuleEvaluationEngine getRuleEvaluationEngine() {
+        if (sRuleEvaluationEngine == null) {
+            return new RuleEvaluationEngine();
+        }
+        return sRuleEvaluationEngine;
+    }
+
+    /**
+     * Load, and match the list of rules against an app install metadata.
+     *
+     * @param appInstallMetadata Metadata of the app to be installed, and to evaluate the rules
+     *                           against.
+     * @return A rule matching the metadata. If there are multiple matching rules, returns any. If
+     * no rules are matching, returns {@link Rule#EMPTY}.
+     */
+    public IntegrityCheckResult evaluate(AppInstallMetadata appInstallMetadata) {
+        List<Rule> rules = loadRules(appInstallMetadata);
+        Rule matchedRule = RuleEvaluator.evaluateRules(rules, appInstallMetadata);
+        if (matchedRule == Rule.EMPTY) {
+            return IntegrityCheckResult.allow();
+        } else {
+            switch (matchedRule.getEffect()) {
+                case DENY:
+                    return IntegrityCheckResult.deny(matchedRule);
+                default:
+                    Slog.e(TAG, "Matched a non-DENY rule: " + matchedRule);
+                    return IntegrityCheckResult.allow();
+            }
+        }
+    }
+
+    private List<Rule> loadRules(AppInstallMetadata appInstallMetadata) {
+        // TODO: Load rules
+        return new ArrayList<>();
+    }
+}
diff --git a/services/core/java/com/android/server/integrity/engine/RuleEvaluator.java b/services/core/java/com/android/server/integrity/engine/RuleEvaluator.java
new file mode 100644
index 0000000..4ed581d
--- /dev/null
+++ b/services/core/java/com/android/server/integrity/engine/RuleEvaluator.java
@@ -0,0 +1,105 @@
+/*
+ * 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.integrity.engine;
+
+import android.util.Slog;
+
+import com.android.server.integrity.model.AppInstallMetadata;
+import com.android.server.integrity.model.AtomicFormula;
+import com.android.server.integrity.model.Formula;
+import com.android.server.integrity.model.OpenFormula;
+import com.android.server.integrity.model.Rule;
+
+import java.util.List;
+
+/**
+ * A helper class for evaluating rules against app install metadata to find if there are matching
+ * rules.
+ */
+final class RuleEvaluator {
+
+    private static final String TAG = "RuleEvaluator";
+
+    /**
+     * Match the list of rules against an app install metadata.
+     *
+     * @param rules              The list of rules to evaluate.
+     * @param appInstallMetadata Metadata of the app to be installed, and to evaluate the rules
+     *                           against.
+     * @return A rule matching the metadata. If there are multiple matching rules, returns any. If
+     * no rules are matching, returns {@link Rule#EMPTY}.
+     */
+    static Rule evaluateRules(List<Rule> rules, AppInstallMetadata appInstallMetadata) {
+        for (Rule rule : rules) {
+            if (isMatch(rule, appInstallMetadata)) {
+                return rule;
+            }
+        }
+        return Rule.EMPTY;
+    }
+
+    /**
+     * Match a rule against app install metadata.
+     */
+    private static boolean isMatch(Rule rule, AppInstallMetadata appInstallMetadata) {
+        return isMatch(rule.getFormula(), appInstallMetadata);
+    }
+
+    private static boolean isMatch(Formula formula, AppInstallMetadata appInstallMetadata) {
+        if (formula instanceof AtomicFormula) {
+            AtomicFormula atomicFormula = (AtomicFormula) formula;
+            switch (atomicFormula.getKey()) {
+                case PACKAGE_NAME:
+                    return atomicFormula.isMatch(appInstallMetadata.getPackageName());
+                case APP_CERTIFICATE:
+                    return atomicFormula.isMatch(appInstallMetadata.getAppCertificate());
+                case INSTALLER_NAME:
+                    return atomicFormula.isMatch(appInstallMetadata.getInstallerName());
+                case INSTALLER_CERTIFICATE:
+                    return atomicFormula.isMatch(appInstallMetadata.getInstallerCertificate());
+                case VERSION_CODE:
+                    return atomicFormula.isMatch(appInstallMetadata.getVersionCode());
+                case PRE_INSTALLED:
+                    return atomicFormula.isMatch(appInstallMetadata.isPreInstalled());
+                default:
+                    Slog.i(TAG, String.format("Returned no match for unknown key %s",
+                            atomicFormula.getKey()));
+                    return false;
+            }
+        } else if (formula instanceof OpenFormula) {
+            OpenFormula openFormula = (OpenFormula) formula;
+            // A rule is in disjunctive normal form, so there are no OR connectors.
+            switch (openFormula.getConnector()) {
+                case NOT:
+                    // NOT connector has only 1 formula attached.
+                    return !isMatch(openFormula.getFormulas().get(0), appInstallMetadata);
+                case AND:
+                    boolean result = true;
+                    for (Formula subFormula : openFormula.getFormulas()) {
+                        result &= isMatch(subFormula, appInstallMetadata);
+                    }
+                    return result;
+                default:
+                    Slog.i(TAG, String.format("Returned no match for unknown connector %s",
+                            openFormula.getConnector()));
+                    return false;
+            }
+        }
+
+        return false;
+    }
+}
diff --git a/services/core/java/com/android/server/integrity/engine/RuleLoader.java b/services/core/java/com/android/server/integrity/engine/RuleLoader.java
new file mode 100644
index 0000000..af24d7a
--- /dev/null
+++ b/services/core/java/com/android/server/integrity/engine/RuleLoader.java
@@ -0,0 +1,61 @@
+/*
+ * 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.integrity.engine;
+
+import com.android.server.integrity.model.Rule;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * A helper class for loading rules to the rule evaluation engine.
+ *
+ * <p>Expose fine-grained APIs for loading rules to be passed to the rule evaluation engine.
+ *
+ * <p>It supports:
+ * <ul>
+ *     <li>Loading rules based on some keys, such as PACKAGE_NAME and APP_CERT.</li>
+ * </ul>
+ *
+ * <p>It does NOT support:
+ * <ul>
+ *     <li>Loading the list of all rules.</li>
+ *     <li>Merging rules resulting from different APIs.</li>
+ * </ul>
+ */
+final class RuleLoader {
+
+    List<Rule> loadRulesByPackageName(String packageName) {
+        // TODO: Add logic based on rule storage.
+        return new ArrayList<>();
+    }
+
+    List<Rule> loadRulesByAppCertificate(String appCertificate) {
+        // TODO: Add logic based on rule storage.
+        return new ArrayList<>();
+    }
+
+    List<Rule> loadRulesByInstallerName(String installerName) {
+        // TODO: Add logic based on rule storage.
+        return new ArrayList<>();
+    }
+
+    List<Rule> loadRulesByInstallerCertificate(String installerCertificate) {
+        // TODO: Add logic based on rule storage.
+        return new ArrayList<>();
+    }
+}
diff --git a/services/core/java/com/android/server/integrity/model/AppInstallMetadata.java b/services/core/java/com/android/server/integrity/model/AppInstallMetadata.java
new file mode 100644
index 0000000..660bd2e
--- /dev/null
+++ b/services/core/java/com/android/server/integrity/model/AppInstallMetadata.java
@@ -0,0 +1,169 @@
+/*
+ * 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.integrity.model;
+
+import static com.android.internal.util.Preconditions.checkArgument;
+import static com.android.internal.util.Preconditions.checkNotNull;
+
+import android.annotation.Nullable;
+
+/**
+ * The app install metadata.
+ *
+ * <p>The integrity component retrieves metadata for app installs from package manager, passing it
+ * to the rule evaluation engine to evaluate the metadata against the rules.
+ *
+ * <p>Instances of this class are immutable.
+ */
+public final class AppInstallMetadata {
+    private final String mPackageName;
+    // Raw string encoding for the SHA-256 hash of the certificate of the app.
+    private final String mAppCertificate;
+    private final String mInstallerName;
+    // Raw string encoding for the SHA-256 hash of the certificate of the installer.
+    private final String mInstallerCertificate;
+    private final int mVersionCode;
+    private final boolean mIsPreInstalled;
+
+    private AppInstallMetadata(Builder builder) {
+        this.mPackageName = builder.mPackageName;
+        this.mAppCertificate = builder.mAppCertificate;
+        this.mInstallerName = builder.mInstallerName;
+        this.mInstallerCertificate = builder.mInstallerCertificate;
+        this.mVersionCode = builder.mVersionCode;
+        this.mIsPreInstalled = builder.mIsPreInstalled;
+    }
+
+    public String getPackageName() {
+        return mPackageName;
+    }
+
+    public String getAppCertificate() {
+        return mAppCertificate;
+    }
+
+    @Nullable
+    public String getInstallerName() {
+        return mInstallerName;
+    }
+
+    @Nullable
+    public String getInstallerCertificate() {
+        return mInstallerCertificate;
+    }
+
+    /**
+     * @see AppInstallMetadata.Builder#setVersionCode(int)
+     */
+    public int getVersionCode() {
+        return mVersionCode;
+    }
+
+    /**
+     * @see AppInstallMetadata.Builder#setIsPreInstalled(boolean)
+     */
+    public boolean isPreInstalled() {
+        return mIsPreInstalled;
+    }
+
+    /**
+     * Builder class for constructing {@link AppInstallMetadata} objects.
+     */
+    public static final class Builder {
+        private String mPackageName;
+        private String mAppCertificate;
+        private String mInstallerName;
+        private String mInstallerCertificate;
+        private int mVersionCode;
+        private boolean mIsPreInstalled;
+
+        /**
+         * Set package name of the app to be installed.
+         *
+         * @see AppInstallMetadata#getPackageName()
+         */
+        public Builder setPackageName(String packageName) {
+            this.mPackageName = checkNotNull(packageName);
+            return this;
+        }
+
+        /**
+         * Set certificate of the app to be installed.
+         *
+         * <p>It is represented as the raw string encoding for the SHA-256 hash of the certificate
+         * of the app.
+         *
+         * @see AppInstallMetadata#getAppCertificate()
+         */
+        public Builder setAppCertificate(String appCertificate) {
+            this.mAppCertificate = checkNotNull(appCertificate);
+            return this;
+        }
+
+        /**
+         * Set name of the installer installing the app.
+         *
+         * @see AppInstallMetadata#getInstallerName()
+         */
+        public Builder setInstallerName(String installerName) {
+            this.mInstallerName = checkNotNull(installerName);
+            return this;
+        }
+
+        /**
+         * Set certificate of the installer installing the app.
+         *
+         * <p>It is represented as the raw string encoding for the SHA-256 hash of the certificate
+         * of the installer.
+         *
+         * @see AppInstallMetadata#getInstallerCertificate()
+         */
+        public Builder setInstallerCertificate(String installerCertificate) {
+            this.mInstallerCertificate = checkNotNull(installerCertificate);
+            return this;
+        }
+
+        /**
+         * Set version code of the app to be installed.
+         *
+         * @see AppInstallMetadata#getVersionCode()
+         */
+        public Builder setVersionCode(int versionCode) {
+            this.mVersionCode = versionCode;
+            return this;
+        }
+
+        /**
+         * Set whether the app is pre-installed on the device or not.
+         *
+         * @see AppInstallMetadata#isPreInstalled()
+         */
+        public Builder setIsPreInstalled(boolean isPreInstalled) {
+            this.mIsPreInstalled = isPreInstalled;
+            return this;
+        }
+
+        /**
+         * Build {@link AppInstallMetadata}.
+         */
+        public AppInstallMetadata build() {
+            checkArgument(mPackageName != null);
+            checkArgument(mAppCertificate != null);
+            return new AppInstallMetadata(this);
+        }
+    }
+}
diff --git a/services/core/java/com/android/server/integrity/model/AtomicFormula.java b/services/core/java/com/android/server/integrity/model/AtomicFormula.java
new file mode 100644
index 0000000..b9b46e3
--- /dev/null
+++ b/services/core/java/com/android/server/integrity/model/AtomicFormula.java
@@ -0,0 +1,236 @@
+/*
+ * 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.integrity.model;
+
+import static com.android.internal.util.Preconditions.checkArgument;
+import static com.android.internal.util.Preconditions.checkNotNull;
+
+import android.annotation.Nullable;
+import android.util.Slog;
+
+import java.util.Objects;
+
+/**
+ * Represents a simple formula consisting of an app install metadata field and a value.
+ *
+ * <p>Instances of this class are immutable.
+ */
+public final class AtomicFormula extends Formula {
+
+    private static final String TAG = "AtomicFormula";
+
+    public enum Key {
+        PACKAGE_NAME,
+        APP_CERTIFICATE,
+        INSTALLER_NAME,
+        INSTALLER_CERTIFICATE,
+        VERSION_CODE,
+        PRE_INSTALLED
+    }
+
+    public enum Operator {
+        EQ,
+        LT,
+        LE,
+        GT,
+        GE
+    }
+
+    private final Key mKey;
+    private final Operator mOperator;
+
+    // The value of a key can take either 1 of 3 forms: String, Integer, or Boolean.
+    // It cannot have multiple values.
+    @Nullable
+    private final String mStringValue;
+    @Nullable
+    private final Integer mIntValue;
+    @Nullable
+    private final Boolean mBoolValue;
+
+    public AtomicFormula(Key key, Operator operator, String stringValue) {
+        validateOperator(key, operator);
+        checkArgument(
+                key == Key.PACKAGE_NAME || key == Key.APP_CERTIFICATE || key == Key.INSTALLER_NAME
+                        || key == Key.INSTALLER_CERTIFICATE,
+                String.format("Key %s cannot have string value", key));
+        this.mKey = checkNotNull(key);
+        this.mOperator = checkNotNull(operator);
+        this.mStringValue = checkNotNull(stringValue);
+        this.mIntValue = null;
+        this.mBoolValue = null;
+    }
+
+    public AtomicFormula(Key key, Operator operator, Integer intValue) {
+        validateOperator(key, operator);
+        checkArgument(key == Key.VERSION_CODE,
+                String.format("Key %s cannot have integer value", key));
+        this.mKey = checkNotNull(key);
+        this.mOperator = checkNotNull(operator);
+        this.mStringValue = null;
+        this.mIntValue = checkNotNull(intValue);
+        this.mBoolValue = null;
+    }
+
+    public AtomicFormula(Key key, Operator operator, Boolean boolValue) {
+        validateOperator(key, operator);
+        checkArgument(key == Key.PRE_INSTALLED,
+                String.format("Key %s cannot have boolean value", key));
+        this.mKey = checkNotNull(key);
+        this.mOperator = checkNotNull(operator);
+        this.mStringValue = null;
+        this.mIntValue = null;
+        this.mBoolValue = checkNotNull(boolValue);
+    }
+
+    public Key getKey() {
+        return mKey;
+    }
+
+    public Operator getOperator() {
+        return mOperator;
+    }
+
+    public String getStringValue() {
+        return mStringValue;
+    }
+
+    public Integer getIntValue() {
+        return mIntValue;
+    }
+
+    public Boolean getBoolValue() {
+        return mBoolValue;
+    }
+
+    /**
+     * Get string representation of the value of the key in the formula.
+     *
+     * @return string representation of the value of the key.
+     */
+    public String getValue() {
+        if (mStringValue != null) {
+            return mStringValue;
+        }
+        if (mIntValue != null) {
+            return mIntValue.toString();
+        }
+        return mBoolValue.toString();
+    }
+
+    /**
+     * Check if the formula is true when substituting its {@link Key} with the string value.
+     *
+     * @param value String value to substitute the key with.
+     * @return {@code true} if the formula is true, and {@code false} otherwise.
+     */
+    public boolean isMatch(String value) {
+        switch (mOperator) {
+            case EQ:
+                return mStringValue.equals(value);
+        }
+        Slog.i(TAG, String.format("Found operator %s for value %s", mOperator, mStringValue));
+        return false;
+    }
+
+    /**
+     * Check if the formula is true when substituting its {@link Key} with the integer value.
+     *
+     * @param value Integer value to substitute the key with.
+     * @return {@code true} if the formula is true, and {@code false} otherwise.
+     */
+    public boolean isMatch(int value) {
+        switch (mOperator) {
+            case EQ:
+                return mIntValue == value;
+            case LE:
+                return mIntValue <= value;
+            case LT:
+                return mIntValue < value;
+            case GE:
+                return mIntValue >= value;
+            case GT:
+                return mIntValue > value;
+        }
+        Slog.i(TAG, String.format("Found operator %s for value %s", mOperator, mIntValue));
+        return false;
+    }
+
+    /**
+     * Check if the formula is true when substituting its {@link Key} with the boolean value.
+     *
+     * @param value Boolean value to substitute the key with.
+     * @return {@code true} if the formula is true, and {@code false} otherwise.
+     */
+    public boolean isMatch(boolean value) {
+        switch (mOperator) {
+            case EQ:
+                return mBoolValue == value;
+        }
+        Slog.i(TAG, String.format("Found operator %s for value %s", mOperator, mBoolValue));
+        return false;
+    }
+
+    @Override
+    public String toString() {
+        return String.format("%s %s %s", mKey, mOperator, getValue());
+    }
+
+    @Override
+    public boolean equals(Object o) {
+        if (this == o) {
+            return true;
+        }
+        if (o == null || getClass() != o.getClass()) {
+            return false;
+        }
+        AtomicFormula that = (AtomicFormula) o;
+        return mKey == that.mKey
+                && mOperator == that.mOperator
+                && Objects.equals(mStringValue, that.mStringValue)
+                && Objects.equals(mIntValue, that.mIntValue)
+                && Objects.equals(mBoolValue, that.mBoolValue);
+    }
+
+    @Override
+    public int hashCode() {
+        return Objects.hash(mKey, mOperator, mStringValue, mIntValue, mBoolValue);
+    }
+
+    private void validateOperator(Key key, Operator operator) {
+        boolean validOperator;
+        switch (key) {
+            case PACKAGE_NAME:
+            case APP_CERTIFICATE:
+            case INSTALLER_NAME:
+            case INSTALLER_CERTIFICATE:
+            case PRE_INSTALLED:
+                validOperator = (operator == Operator.EQ);
+                break;
+            case VERSION_CODE:
+                validOperator = true;
+                break;
+            default:
+                Slog.i(TAG, String.format("Found operator %s for key %s", operator, key));
+                validOperator = false;
+        }
+        if (!validOperator) {
+            throw new IllegalArgumentException(
+                    String.format("Invalid operator %s used for key %s", operator, key));
+        }
+    }
+}
diff --git a/core/java/android/hardware/biometrics/IBiometricConfirmDeviceCredentialCallback.aidl b/services/core/java/com/android/server/integrity/model/Formula.java
similarity index 68%
copy from core/java/android/hardware/biometrics/IBiometricConfirmDeviceCredentialCallback.aidl
copy to services/core/java/com/android/server/integrity/model/Formula.java
index 8b35852..9db4453 100644
--- a/core/java/android/hardware/biometrics/IBiometricConfirmDeviceCredentialCallback.aidl
+++ b/services/core/java/com/android/server/integrity/model/Formula.java
@@ -14,13 +14,11 @@
  * limitations under the License.
  */
 
-package android.hardware.biometrics;
+package com.android.server.integrity.model;
 
 /**
- * Communication channel between ConfirmDeviceCredential / ConfirmLock* and BiometricService.
- * @hide
+ * Represents a rule logic/content.
  */
-interface IBiometricConfirmDeviceCredentialCallback {
-    // Invoked when authentication should be canceled.
-    oneway void cancel();
-}
\ No newline at end of file
+public abstract class Formula {
+
+}
diff --git a/services/core/java/com/android/server/integrity/model/IntegrityCheckResult.java b/services/core/java/com/android/server/integrity/model/IntegrityCheckResult.java
new file mode 100644
index 0000000..7aeb0c1
--- /dev/null
+++ b/services/core/java/com/android/server/integrity/model/IntegrityCheckResult.java
@@ -0,0 +1,67 @@
+/*
+ * 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.integrity.model;
+
+/**
+ * A class encapsulating the result from the evaluation engine after evaluating rules against app
+ * install metadata.
+ *
+ * <p>It contains the outcome effect (whether to allow or block the install), and the rule causing
+ * that effect.
+ */
+public final class IntegrityCheckResult {
+
+    public enum Effect {
+        ALLOW,
+        DENY
+    }
+
+    private final Effect mEffect;
+    private final Rule mRule;
+
+    private IntegrityCheckResult(Effect effect, Rule rule) {
+        this.mEffect = effect;
+        this.mRule = rule;
+    }
+
+    public Effect getEffect() {
+        return mEffect;
+    }
+
+    public Rule getRule() {
+        return mRule;
+    }
+
+    /**
+     * Create an ALLOW evaluation outcome.
+     *
+     * @return An evaluation outcome with ALLOW effect and empty rule.
+     */
+    public static IntegrityCheckResult allow() {
+        return new IntegrityCheckResult(Effect.ALLOW, Rule.EMPTY);
+    }
+
+    /**
+     * Create a DENY evaluation outcome.
+     *
+     * @param rule Rule causing the DENY effect.
+     * @return An evaluation outcome with DENY effect and rule causing that effect.
+     */
+    public static IntegrityCheckResult deny(Rule rule) {
+        return new IntegrityCheckResult(Effect.DENY, rule);
+    }
+}
diff --git a/services/core/java/com/android/server/integrity/model/OpenFormula.java b/services/core/java/com/android/server/integrity/model/OpenFormula.java
new file mode 100644
index 0000000..21da629
--- /dev/null
+++ b/services/core/java/com/android/server/integrity/model/OpenFormula.java
@@ -0,0 +1,99 @@
+/*
+ * 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.integrity.model;
+
+import static com.android.internal.util.Preconditions.checkArgument;
+import static com.android.internal.util.Preconditions.checkNotNull;
+
+import java.util.Collections;
+import java.util.List;
+import java.util.Objects;
+
+/**
+ * Represents a complex formula consisting of other simple and complex formulas.
+ *
+ * <p>Instances of this class are immutable.
+ */
+public final class OpenFormula extends Formula {
+
+    public enum Connector {
+        AND,
+        OR,
+        NOT
+    }
+
+    private final Connector mConnector;
+    private final List<Formula> mFormulas;
+
+    public OpenFormula(Connector connector, List<Formula> formulas) {
+        validateFormulas(connector, formulas);
+        this.mConnector = checkNotNull(connector);
+        this.mFormulas = Collections.unmodifiableList(checkNotNull(formulas));
+    }
+
+    public Connector getConnector() {
+        return mConnector;
+    }
+
+    public List<Formula> getFormulas() {
+        return mFormulas;
+    }
+
+    @Override
+    public String toString() {
+        StringBuilder sb = new StringBuilder();
+        for (int i = 0; i < mFormulas.size(); i++) {
+            if (i > 0) {
+                sb.append(String.format(" %s ", mConnector));
+            }
+            sb.append(mFormulas.get(i).toString());
+        }
+        return sb.toString();
+    }
+
+    @Override
+    public boolean equals(Object o) {
+        if (this == o) {
+            return true;
+        }
+        if (o == null || getClass() != o.getClass()) {
+            return false;
+        }
+        OpenFormula that = (OpenFormula) o;
+        return mConnector == that.mConnector
+                && mFormulas.equals(that.mFormulas);
+    }
+
+    @Override
+    public int hashCode() {
+        return Objects.hash(mConnector, mFormulas);
+    }
+
+    private void validateFormulas(Connector connector, List<Formula> formulas) {
+        switch (connector) {
+            case AND:
+            case OR:
+                checkArgument(formulas.size() >= 2,
+                        String.format("Connector %s must have at least 2 formulas", connector));
+                break;
+            case NOT:
+                checkArgument(formulas.size() == 1,
+                        String.format("Connector %s must have 1 formula only", connector));
+                break;
+        }
+    }
+}
diff --git a/services/core/java/com/android/server/integrity/model/Rule.java b/services/core/java/com/android/server/integrity/model/Rule.java
new file mode 100644
index 0000000..ff21d6f
--- /dev/null
+++ b/services/core/java/com/android/server/integrity/model/Rule.java
@@ -0,0 +1,89 @@
+/*
+ * 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.integrity.model;
+
+import static com.android.internal.util.Preconditions.checkNotNull;
+
+import java.util.Objects;
+
+/**
+ * Represent rules to be used in the rule evaluation engine to match against app installs.
+ *
+ * <p>Instances of this class are immutable.
+ */
+public final class Rule {
+
+    public enum Effect {
+        DENY
+    }
+
+    // Holds an empty rule instance.
+    public static final Rule EMPTY = new Rule();
+
+    private final Formula mFormula;
+    private final Effect mEffect;
+
+    private Rule() {
+        this.mFormula = null;
+        this.mEffect = null;
+    }
+
+    public Rule(Formula formula, Effect effect) {
+        this.mFormula = checkNotNull(formula);
+        this.mEffect = checkNotNull(effect);
+    }
+
+    /**
+     * Indicates whether the rule is empty or not.
+     *
+     * @return {@code true} if the rule is empty, and {@code false} otherwise.
+     */
+    public boolean isEmpty() {
+        return mFormula == null && mEffect == null;
+    }
+
+    public Formula getFormula() {
+        return mFormula;
+    }
+
+    public Effect getEffect() {
+        return mEffect;
+    }
+
+    @Override
+    public String toString() {
+        return String.format("Rule: %s, %s", mFormula, mEffect);
+    }
+
+    @Override
+    public boolean equals(Object o) {
+        if (this == o) {
+            return true;
+        }
+        if (o == null || getClass() != o.getClass()) {
+            return false;
+        }
+        Rule that = (Rule) o;
+        return mFormula.equals(that.mFormula)
+                && mEffect == that.mEffect;
+    }
+
+    @Override
+    public int hashCode() {
+        return Objects.hash(mFormula, mEffect);
+    }
+}
diff --git a/services/core/java/com/android/server/location/GnssLocationProvider.java b/services/core/java/com/android/server/location/GnssLocationProvider.java
index c6226fa..8bf01a3 100644
--- a/services/core/java/com/android/server/location/GnssLocationProvider.java
+++ b/services/core/java/com/android/server/location/GnssLocationProvider.java
@@ -74,6 +74,8 @@
 import com.android.internal.location.ProviderRequest;
 import com.android.internal.location.gnssmetrics.GnssMetrics;
 import com.android.internal.telephony.TelephonyIntents;
+import com.android.server.DeviceIdleInternal;
+import com.android.server.LocalServices;
 import com.android.server.location.GnssSatelliteBlacklistHelper.GnssSatelliteBlacklistCallback;
 import com.android.server.location.NtpTimeHelper.InjectNtpTimeCallback;
 
@@ -177,6 +179,7 @@
     private static final int AGPS_SUPL_MODE_MSA = 0x02;
     private static final int AGPS_SUPL_MODE_MSB = 0x01;
 
+    private static final int UPDATE_LOW_POWER_MODE = 1;
     private static final int SET_REQUEST = 3;
     private static final int INJECT_NTP_TIME = 5;
     // PSDS stands for Predicted Satellite Data Service
@@ -360,6 +363,12 @@
     private boolean mDisableGpsForPowerManager = false;
 
     /**
+     * True if the device idle controller has determined that the device is stationary. This is only
+     * updated when the device enters idle mode.
+     */
+    private volatile boolean mIsDeviceStationary = false;
+
+    /**
      * Properties loaded from PROPERTIES_FILE.
      * It must be accessed only inside {@link #mHandler}.
      */
@@ -451,6 +460,15 @@
     public GnssNavigationMessageProvider getGnssNavigationMessageProvider() {
         return mGnssNavigationMessageProvider;
     }
+
+    private final DeviceIdleInternal.StationaryListener mDeviceIdleStationaryListener =
+            isStationary -> {
+                mIsDeviceStationary = isStationary;
+                // Call updateLowPowerMode on handler thread so it's always called from the same
+                // thread.
+                mHandler.sendEmptyMessage(UPDATE_LOW_POWER_MODE);
+            };
+
     private final BroadcastReceiver mBroadcastReceiver = new BroadcastReceiver() {
         @Override
         public void onReceive(Context context, Intent intent) {
@@ -467,11 +485,22 @@
                 case ALARM_TIMEOUT:
                     hibernate();
                     break;
-                case PowerManager.ACTION_POWER_SAVE_MODE_CHANGED:
                 case PowerManager.ACTION_DEVICE_IDLE_MODE_CHANGED:
+                    DeviceIdleInternal deviceIdleService = LocalServices.getService(
+                            DeviceIdleInternal.class);
+                    if (mPowerManager.isDeviceIdleMode()) {
+                        deviceIdleService.registerStationaryListener(mDeviceIdleStationaryListener);
+                    } else {
+                        deviceIdleService.unregisterStationaryListener(
+                                mDeviceIdleStationaryListener);
+                    }
+                    // Intentional fall-through.
+                case PowerManager.ACTION_POWER_SAVE_MODE_CHANGED:
                 case Intent.ACTION_SCREEN_OFF:
                 case Intent.ACTION_SCREEN_ON:
-                    updateLowPowerMode();
+                    // Call updateLowPowerMode on handler thread so it's always called from the
+                    // same thread.
+                    mHandler.sendEmptyMessage(UPDATE_LOW_POWER_MODE);
                     break;
                 case CarrierConfigManager.ACTION_CARRIER_CONFIG_CHANGED:
                 case TelephonyIntents.ACTION_DEFAULT_DATA_SUBSCRIPTION_CHANGED:
@@ -529,10 +558,9 @@
     }
 
     private void updateLowPowerMode() {
-        // Disable GPS if we are in device idle mode.
-        boolean disableGpsForPowerManager = mPowerManager.isDeviceIdleMode();
-        final PowerSaveState result =
-                mPowerManager.getPowerSaveState(ServiceType.LOCATION);
+        // Disable GPS if we are in device idle mode and the device is stationary.
+        boolean disableGpsForPowerManager = mPowerManager.isDeviceIdleMode() && mIsDeviceStationary;
+        final PowerSaveState result = mPowerManager.getPowerSaveState(ServiceType.LOCATION);
         switch (result.locationMode) {
             case PowerManager.LOCATION_MODE_GPS_DISABLED_WHEN_SCREEN_OFF:
             case PowerManager.LOCATION_MODE_ALL_DISABLED_WHEN_SCREEN_OFF:
@@ -2005,6 +2033,9 @@
                 case REPORT_SV_STATUS:
                     handleReportSvStatus((SvStatusInfo) msg.obj);
                     break;
+                case UPDATE_LOW_POWER_MODE:
+                    updateLowPowerMode();
+                    break;
             }
             if (msg.arg2 == 1) {
                 // wakelock was taken for this message, release it
diff --git a/services/core/java/com/android/server/locksettings/LockSettingsService.java b/services/core/java/com/android/server/locksettings/LockSettingsService.java
index 378d9eb..bad484f 100644
--- a/services/core/java/com/android/server/locksettings/LockSettingsService.java
+++ b/services/core/java/com/android/server/locksettings/LockSettingsService.java
@@ -61,7 +61,10 @@
 import android.database.sqlite.SQLiteDatabase;
 import android.hardware.authsecret.V1_0.IAuthSecret;
 import android.hardware.biometrics.BiometricManager;
+import android.hardware.face.Face;
 import android.hardware.face.FaceManager;
+import android.hardware.fingerprint.Fingerprint;
+import android.hardware.fingerprint.FingerprintManager;
 import android.net.Uri;
 import android.os.Binder;
 import android.os.Bundle;
@@ -117,6 +120,7 @@
 import com.android.internal.widget.LockSettingsInternal;
 import com.android.internal.widget.VerifyCredentialResponse;
 import com.android.server.LocalServices;
+import com.android.server.ServiceThread;
 import com.android.server.SystemService;
 import com.android.server.locksettings.LockSettingsStorage.CredentialHash;
 import com.android.server.locksettings.LockSettingsStorage.PersistentData;
@@ -387,8 +391,15 @@
             return mContext;
         }
 
-        public Handler getHandler() {
-            return new Handler();
+        public ServiceThread getServiceThread() {
+            ServiceThread handlerThread = new ServiceThread(TAG, Process.THREAD_PRIORITY_BACKGROUND,
+                    true /*allowIo*/);
+            handlerThread.start();
+            return handlerThread;
+        }
+
+        public Handler getHandler(ServiceThread handlerThread) {
+            return new Handler(handlerThread.getLooper());
         }
 
         public LockSettingsStorage getStorage() {
@@ -483,6 +494,23 @@
         public boolean isGsiRunning() {
             return SystemProperties.getInt(GSI_RUNNING_PROP, 0) > 0;
         }
+
+        public FingerprintManager getFingerprintManager() {
+            if (mContext.getPackageManager().hasSystemFeature(PackageManager.FEATURE_FINGERPRINT)) {
+                return (FingerprintManager) mContext.getSystemService(Context.FINGERPRINT_SERVICE);
+            } else {
+                return null;
+            }
+        }
+
+        public FaceManager getFaceManager() {
+            if (mContext.getPackageManager().hasSystemFeature(PackageManager.FEATURE_FACE)) {
+                return (FaceManager) mContext.getSystemService(Context.FACE_SERVICE);
+            } else {
+                return null;
+            }
+        }
+
     }
 
     public LockSettingsService(Context context) {
@@ -495,7 +523,7 @@
         mContext = injector.getContext();
         mKeyStore = injector.getKeyStore();
         mRecoverableKeyStoreManager = injector.getRecoverableKeyStoreManager(mKeyStore);
-        mHandler = injector.getHandler();
+        mHandler = injector.getHandler(injector.getServiceThread());
         mStrongAuth = injector.getStrongAuth();
         mActivityManager = injector.getActivityManager();
 
@@ -2713,6 +2741,7 @@
             fixateNewestUserKeyAuth(userId);
             unlockKeystore(auth.deriveKeyStorePassword(), userId);
             setKeystorePassword(null, userId);
+            removeBiometricsForUser(userId);
         }
         setSyntheticPasswordHandleLocked(newHandle, userId);
         synchronizeUnifiedWorkChallengeForProfiles(userId, profilePasswords);
@@ -2728,6 +2757,85 @@
         return newHandle;
     }
 
+    private void removeBiometricsForUser(int userId) {
+        removeAllFingerprintForUser(userId);
+        removeAllFaceForUser(userId);
+    }
+
+    private void removeAllFingerprintForUser(final int userId) {
+        FingerprintManager mFingerprintManager = mInjector.getFingerprintManager();
+        if (mFingerprintManager != null && mFingerprintManager.isHardwareDetected()) {
+            if (mFingerprintManager.hasEnrolledFingerprints(userId)) {
+                mFingerprintManager.setActiveUser(userId);
+                CountDownLatch latch = new CountDownLatch(1);
+                // For the purposes of M and N, groupId is the same as userId.
+                Fingerprint finger = new Fingerprint(null, userId, 0, 0);
+                mFingerprintManager.remove(finger, userId,
+                        fingerprintManagerRemovalCallback(latch));
+                try {
+                    latch.await(10000, TimeUnit.MILLISECONDS);
+                } catch (InterruptedException e) {
+                    Slog.e(TAG, "Latch interrupted when removing fingerprint", e);
+                }
+            }
+        }
+    }
+
+    private void removeAllFaceForUser(final int userId) {
+        FaceManager mFaceManager = mInjector.getFaceManager();
+        if (mFaceManager != null && mFaceManager.isHardwareDetected()) {
+            if (mFaceManager.hasEnrolledTemplates(userId)) {
+                mFaceManager.setActiveUser(userId);
+                CountDownLatch latch = new CountDownLatch(1);
+                Face face = new Face(null, 0, 0);
+                mFaceManager.remove(face, userId, faceManagerRemovalCallback(latch));
+                try {
+                    latch.await(10000, TimeUnit.MILLISECONDS);
+                } catch (InterruptedException e) {
+                    Slog.e(TAG, "Latch interrupted when removing face", e);
+                }
+            }
+        }
+    }
+
+    private FingerprintManager.RemovalCallback fingerprintManagerRemovalCallback(
+            CountDownLatch latch) {
+        return new FingerprintManager.RemovalCallback() {
+            @Override
+            public void onRemovalError(Fingerprint fp, int errMsgId, CharSequence err) {
+                Slog.e(TAG, String.format(
+                        "Can't remove fingerprint %d in group %d. Reason: %s",
+                        fp.getBiometricId(), fp.getGroupId(), err));
+                latch.countDown();
+            }
+
+            @Override
+            public void onRemovalSucceeded(Fingerprint fp, int remaining) {
+                if (remaining == 0) {
+                    latch.countDown();
+                }
+            }
+        };
+    }
+
+    private FaceManager.RemovalCallback faceManagerRemovalCallback(CountDownLatch latch) {
+        return new FaceManager.RemovalCallback() {
+            @Override
+            public void onRemovalError(Face face, int errMsgId, CharSequence err) {
+                Slog.e(TAG, String.format("Can't remove face %d. Reason: %s",
+                        face.getBiometricId(), err));
+                latch.countDown();
+            }
+
+            @Override
+            public void onRemovalSucceeded(Face face, int remaining) {
+                if (remaining == 0) {
+                    latch.countDown();
+                }
+            }
+        };
+    }
+
     @GuardedBy("mSpManager")
     private boolean spBasedSetLockCredentialInternalLocked(byte[] credential, int credentialType,
             byte[] savedCredential, int requestedQuality, int userId,
diff --git a/services/core/java/com/android/server/locksettings/TEST_MAPPING b/services/core/java/com/android/server/locksettings/TEST_MAPPING
index c1cba5f..56f5cc0 100644
--- a/services/core/java/com/android/server/locksettings/TEST_MAPPING
+++ b/services/core/java/com/android/server/locksettings/TEST_MAPPING
@@ -1,5 +1,5 @@
 {
-    "presubmit": [
+    "presubmit-devicepolicy": [
         {
             "name": "CtsDevicePolicyManagerTestCases",
             "options": [
diff --git a/services/core/java/com/android/server/media/MediaRouter2ServiceImpl.java b/services/core/java/com/android/server/media/MediaRouter2ServiceImpl.java
index 043c834..668f2be 100644
--- a/services/core/java/com/android/server/media/MediaRouter2ServiceImpl.java
+++ b/services/core/java/com/android/server/media/MediaRouter2ServiceImpl.java
@@ -26,6 +26,7 @@
 import android.content.pm.PackageManager;
 import android.media.IMediaRouter2Client;
 import android.media.IMediaRouter2Manager;
+import android.media.IMediaRouterClient;
 import android.media.MediaRoute2Info;
 import android.media.MediaRoute2ProviderInfo;
 import android.os.Binder;
@@ -86,7 +87,7 @@
         final long token = Binder.clearCallingIdentity();
         try {
             synchronized (mLock) {
-                registerClientLocked(client, uid, pid, packageName, userId, trusted);
+                registerClient2Locked(client, uid, pid, packageName, userId, trusted);
             }
         } finally {
             Binder.restoreCallingIdentity(token);
@@ -99,7 +100,7 @@
         final long token = Binder.clearCallingIdentity();
         try {
             synchronized (mLock) {
-                unregisterClientLocked(client, false);
+                unregisterClient2Locked(client, false);
             }
         } finally {
             Binder.restoreCallingIdentity(token);
@@ -155,14 +156,30 @@
         }
     }
 
-    public void setControlCategories(@NonNull IMediaRouter2Client client,
+    //TODO: What would happen if a media app used MediaRouter and MediaRouter2 simultaneously?
+    public void setControlCategories(@NonNull IMediaRouterClient client,
+            @Nullable List<String> categories) {
+        Objects.requireNonNull(client, "client must not be null");
+        final long token = Binder.clearCallingIdentity();
+        try {
+            synchronized (mLock) {
+                ClientRecord clientRecord = mAllClientRecords.get(client.asBinder());
+                setControlCategoriesLocked(clientRecord, categories);
+            }
+        } finally {
+            Binder.restoreCallingIdentity(token);
+        }
+    }
+
+    public void setControlCategories2(@NonNull IMediaRouter2Client client,
             @Nullable List<String> categories) {
         Objects.requireNonNull(client, "client must not be null");
 
         final long token = Binder.clearCallingIdentity();
         try {
             synchronized (mLock) {
-                setControlCategoriesLocked(client, categories);
+                ClientRecord clientRecord = mAllClientRecords.get(client.asBinder());
+                setControlCategoriesLocked(clientRecord, categories);
             }
         } finally {
             Binder.restoreCallingIdentity(token);
@@ -174,7 +191,7 @@
         final long token = Binder.clearCallingIdentity();
         try {
             synchronized (mLock) {
-                selectRoute2Locked(client, route);
+                selectRoute2Locked(mAllClientRecords.get(client.asBinder()), route);
             }
         } finally {
             Binder.restoreCallingIdentity(token);
@@ -193,6 +210,36 @@
         }
     }
 
+    public void registerClient(@NonNull IMediaRouterClient client, @NonNull String packageName) {
+        Objects.requireNonNull(client, "client must not be null");
+
+        final int uid = Binder.getCallingUid();
+        final int pid = Binder.getCallingPid();
+        final int userId = UserHandle.getUserId(uid);
+
+        final long token = Binder.clearCallingIdentity();
+        try {
+            synchronized (mLock) {
+                registerClient1Locked(client, packageName, userId);
+            }
+        } finally {
+            Binder.restoreCallingIdentity(token);
+        }
+    }
+
+    public void unregisterClient(@NonNull IMediaRouterClient client) {
+        Objects.requireNonNull(client, "client must not be null");
+
+        final long token = Binder.clearCallingIdentity();
+        try {
+            synchronized (mLock) {
+                unregisterClient1Locked(client);
+            }
+        } finally {
+            Binder.restoreCallingIdentity(token);
+        }
+    }
+
     //TODO: Review this is handling multi-user properly.
     void switchUser() {
         synchronized (mLock) {
@@ -217,9 +264,9 @@
         }
     }
 
-    void clientDied(ClientRecord clientRecord) {
+    void clientDied(Client2Record clientRecord) {
         synchronized (mLock) {
-            unregisterClientLocked(clientRecord.mClient, true);
+            unregisterClient2Locked(clientRecord.mClient, true);
         }
     }
 
@@ -229,18 +276,18 @@
         }
     }
 
-    private void registerClientLocked(IMediaRouter2Client client,
+    private void registerClient2Locked(IMediaRouter2Client client,
             int uid, int pid, String packageName, int userId, boolean trusted) {
         final IBinder binder = client.asBinder();
-        ClientRecord clientRecord = mAllClientRecords.get(binder);
-        if (clientRecord == null) {
+        if (mAllClientRecords.get(binder) == null) {
             boolean newUser = false;
             UserRecord userRecord = mUserRecords.get(userId);
             if (userRecord == null) {
                 userRecord = new UserRecord(userId);
                 newUser = true;
             }
-            clientRecord = new ClientRecord(userRecord, client, uid, pid, packageName, trusted);
+            Client2Record clientRecord = new Client2Record(userRecord, client, uid, pid,
+                    packageName, trusted);
             try {
                 binder.linkToDeath(clientRecord, 0);
             } catch (RemoteException ex) {
@@ -261,8 +308,8 @@
         }
     }
 
-    private void unregisterClientLocked(IMediaRouter2Client client, boolean died) {
-        ClientRecord clientRecord = mAllClientRecords.remove(client.asBinder());
+    private void unregisterClient2Locked(IMediaRouter2Client client, boolean died) {
+        Client2Record clientRecord = (Client2Record) mAllClientRecords.remove(client.asBinder());
         if (clientRecord != null) {
             UserRecord userRecord = clientRecord.mUserRecord;
             userRecord.mClientRecords.remove(clientRecord);
@@ -272,8 +319,7 @@
         }
     }
 
-    private void selectRoute2Locked(IMediaRouter2Client client, MediaRoute2Info route) {
-        ClientRecord clientRecord = mAllClientRecords.get(client.asBinder());
+    private void selectRoute2Locked(ClientRecord clientRecord, MediaRoute2Info route) {
         if (clientRecord != null) {
             MediaRoute2Info oldRoute = clientRecord.mSelectedRoute;
             clientRecord.mSelectedRoute = route;
@@ -294,10 +340,7 @@
         }
     }
 
-    private void setControlCategoriesLocked(IMediaRouter2Client client, List<String> categories) {
-        final IBinder binder = client.asBinder();
-        ClientRecord clientRecord = mAllClientRecords.get(binder);
-
+    private void setControlCategoriesLocked(ClientRecord clientRecord, List<String> categories) {
         if (clientRecord != null) {
             clientRecord.mControlCategories = categories;
 
@@ -349,9 +392,7 @@
                     obtainMessage(UserHandler::notifyProviderInfosUpdatedToManager,
                             userRecord.mHandler, manager));
 
-            final int count = userRecord.mClientRecords.size();
-            for (int i = 0; i < count; i++) {
-                ClientRecord clientRecord = userRecord.mClientRecords.get(i);
+            for (ClientRecord clientRecord : userRecord.mClientRecords) {
                 clientRecord.mUserRecord.mHandler.sendMessage(
                         obtainMessage(UserHandler::updateClientUsage,
                             clientRecord.mUserRecord.mHandler, clientRecord));
@@ -378,7 +419,7 @@
                 Slog.w(TAG, "Ignoring route selection for unknown client.");
             }
             if (clientRecord != null && managerRecord.mTrusted) {
-                selectRoute2Locked(clientRecord.mClient, route);
+                selectRoute2Locked(clientRecord, route);
             }
         }
     }
@@ -409,6 +450,37 @@
         }
     }
 
+    private void registerClient1Locked(IMediaRouterClient client, String packageName,
+            int userId) {
+        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;
+            }
+            ClientRecord clientRecord = new Client1Record(userRecord, client, packageName);
+
+            if (newUser) {
+                mUserRecords.put(userId, userRecord);
+                initializeUserLocked(userRecord);
+            }
+
+            userRecord.mClientRecords.add(clientRecord);
+            mAllClientRecords.put(binder, clientRecord);
+        }
+    }
+
+    private void unregisterClient1Locked(IMediaRouterClient client) {
+        ClientRecord clientRecord = mAllClientRecords.remove(client.asBinder());
+        if (clientRecord != null) {
+            UserRecord userRecord = clientRecord.mUserRecord;
+            userRecord.mClientRecords.remove(clientRecord);
+            disposeUserIfNeededLocked(userRecord);
+        }
+    }
+
     final class UserRecord {
         public final int mUserId;
         final ArrayList<ClientRecord> mClientRecords = new ArrayList<>();
@@ -430,25 +502,43 @@
         }
     }
 
-    final class ClientRecord implements IBinder.DeathRecipient {
+    class ClientRecord {
         public final UserRecord mUserRecord;
-        public final IMediaRouter2Client mClient;
-        public final int mUid;
-        public final int mPid;
         public final String mPackageName;
-        public final boolean mTrusted;
         public List<String> mControlCategories;
         public MediaRoute2Info mSelectedRoute;
 
-        ClientRecord(UserRecord userRecord, IMediaRouter2Client client,
-                int uid, int pid, String packageName, boolean trusted) {
+        ClientRecord(UserRecord userRecord, String packageName) {
             mUserRecord = userRecord;
+            mPackageName = packageName;
+            mControlCategories = Collections.emptyList();
+        }
+    }
+
+    final class Client1Record extends ClientRecord {
+        public final IMediaRouterClient mClient;
+
+        Client1Record(UserRecord userRecord, IMediaRouterClient client,
+                String packageName) {
+            super(userRecord, packageName);
+            mClient = client;
+        }
+    }
+
+    final class Client2Record extends ClientRecord
+            implements IBinder.DeathRecipient {
+        public final IMediaRouter2Client mClient;
+        public final int mUid;
+        public final int mPid;
+        public final boolean mTrusted;
+
+        Client2Record(UserRecord userRecord, IMediaRouter2Client client,
+                int uid, int pid, String packageName, boolean trusted) {
+            super(userRecord, packageName);
             mClient = client;
             mUid = uid;
             mPid = pid;
-            mPackageName = packageName;
             mTrusted = trusted;
-            mControlCategories = Collections.emptyList();
         }
 
         public void dispose() {
@@ -622,7 +712,9 @@
                     managers.add(managerRecord.mManager);
                 }
                 for (ClientRecord clientRecord : mUserRecord.mClientRecords) {
-                    clients.add(clientRecord.mClient);
+                    if (clientRecord instanceof Client2Record) {
+                        clients.add(((Client2Record) clientRecord).mClient);
+                    }
                 }
             }
             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 2670cd8..796a25d 100644
--- a/services/core/java/com/android/server/media/MediaRouterService.java
+++ b/services/core/java/com/android/server/media/MediaRouterService.java
@@ -249,6 +249,7 @@
             synchronized (mLock) {
                 registerClientLocked(client, uid, pid, packageName, resolvedUserId, trusted);
             }
+            mService2.registerClient(client, packageName);
         } finally {
             Binder.restoreCallingIdentity(token);
         }
@@ -289,6 +290,7 @@
             synchronized (mLock) {
                 unregisterClientLocked(client, false);
             }
+            mService2.unregisterClient(client);
         } finally {
             Binder.restoreCallingIdentity(token);
         }
@@ -395,6 +397,12 @@
 
     // Binder call
     @Override
+    public void setControlCategories(IMediaRouterClient client, List<String> controlCategories) {
+        mService2.setControlCategories(client, controlCategories);
+    }
+
+    // Binder call
+    @Override
     public void requestUpdateVolume(IMediaRouterClient client, String routeId, int direction) {
         if (client == null) {
             throw new IllegalArgumentException("client must not be null");
@@ -487,8 +495,8 @@
 
     // Binder call
     @Override
-    public void setControlCategories(IMediaRouter2Client client, List<String> categories) {
-        mService2.setControlCategories(client, categories);
+    public void setControlCategories2(IMediaRouter2Client client, List<String> categories) {
+        mService2.setControlCategories2(client, categories);
     }
 
     void restoreBluetoothA2dp() {
@@ -561,6 +569,7 @@
         synchronized (mLock) {
             unregisterClientLocked(clientRecord.mClient, true);
         }
+        mService2.unregisterClient(clientRecord.mClient);
     }
 
     private void registerClientLocked(IMediaRouterClient client,
diff --git a/services/core/java/com/android/server/notification/GroupHelper.java b/services/core/java/com/android/server/notification/GroupHelper.java
index b1cd627..9cb8a01 100644
--- a/services/core/java/com/android/server/notification/GroupHelper.java
+++ b/services/core/java/com/android/server/notification/GroupHelper.java
@@ -16,9 +16,13 @@
 package com.android.server.notification;
 
 import android.service.notification.StatusBarNotification;
+import android.util.ArrayMap;
+import android.util.ArraySet;
 import android.util.Log;
 import android.util.Slog;
 
+import com.android.internal.annotations.VisibleForTesting;
+
 import java.util.ArrayList;
 import java.util.HashMap;
 import java.util.LinkedHashSet;
@@ -37,6 +41,11 @@
     private final Callback mCallback;
     private final int mAutoGroupAtCount;
 
+    // count the number of ongoing notifications per group
+    // userId -> (package name -> (group Id -> (set of notification keys)))
+    final ArrayMap<String, ArraySet<String>>
+            mOngoingGroupCount = new ArrayMap<>();
+
     // Map of user : <Map of package : notification keys>. Only contains notifications that are not
     // grouped by the app (aka no group or sort key).
     Map<Integer, Map<String, LinkedHashSet<String>>> mUngroupedNotifications = new HashMap<>();
@@ -46,10 +55,52 @@
         mCallback = callback;
     }
 
+    private String generatePackageGroupKey(int userId, String pkg, String group) {
+        return userId + "|" + pkg + "|" + group;
+    }
+
+    @VisibleForTesting
+    protected int getOngoingGroupCount(int userId, String pkg, String group) {
+        String key = generatePackageGroupKey(userId, pkg, group);
+        return mOngoingGroupCount.getOrDefault(key, new ArraySet<>(0)).size();
+    }
+
+    private void addToOngoingGroupCount(StatusBarNotification sbn, boolean add) {
+        if (sbn.getNotification().isGroupSummary()) return;
+        if (!sbn.isOngoing() && add) return;
+        String group = sbn.getGroup();
+        if (group == null) return;
+        int userId = sbn.getUser().getIdentifier();
+        String key = generatePackageGroupKey(userId, sbn.getPackageName(), group);
+        ArraySet<String> notifications = mOngoingGroupCount.getOrDefault(key, new ArraySet<>(0));
+        if (add) {
+            notifications.add(sbn.getKey());
+            mOngoingGroupCount.put(key, notifications);
+        } else {
+            notifications.remove(sbn.getKey());
+            // we dont need to put it back if it is default
+        }
+        String combinedKey = generatePackageGroupKey(userId, sbn.getPackageName(), group);
+        boolean needsOngoingFlag = notifications.size() > 0;
+        mCallback.updateAutogroupSummary(sbn.getKey(), needsOngoingFlag);
+    }
+
+    public void onNotificationUpdated(StatusBarNotification childSbn,
+            boolean autogroupSummaryExists) {
+        if (childSbn.getGroup() != AUTOGROUP_KEY
+                || childSbn.getNotification().isGroupSummary()) return;
+        if (childSbn.isOngoing()) {
+            addToOngoingGroupCount(childSbn, true);
+        } else {
+            addToOngoingGroupCount(childSbn, false);
+        }
+    }
+
     public void onNotificationPosted(StatusBarNotification sbn, boolean autogroupSummaryExists) {
         if (DEBUG) Log.i(TAG, "POSTED " + sbn.getKey());
         try {
             List<String> notificationsToGroup = new ArrayList<>();
+            if (autogroupSummaryExists) addToOngoingGroupCount(sbn, true);
             if (!sbn.isAppGroup()) {
                 // Not grouped by the app, add to the list of notifications for the app;
                 // send grouping update if app exceeds the autogrouping limit.
@@ -90,6 +141,7 @@
 
     public void onNotificationRemoved(StatusBarNotification sbn) {
         try {
+            addToOngoingGroupCount(sbn, false);
             maybeUngroup(sbn, true, sbn.getUserId());
         } catch (Exception e) {
             Slog.e(TAG, "Error processing canceled notification", e);
@@ -159,5 +211,6 @@
         void removeAutoGroup(String key);
         void addAutoGroupSummary(int userId, String pkg, String triggeringKey);
         void removeAutoGroupSummary(int user, String pkg);
+        void updateAutogroupSummary(String key, boolean needsOngoingFlag);
     }
 }
diff --git a/services/core/java/com/android/server/notification/ManagedServices.java b/services/core/java/com/android/server/notification/ManagedServices.java
index 48b0fd6..8560ae6 100644
--- a/services/core/java/com/android/server/notification/ManagedServices.java
+++ b/services/core/java/com/android/server/notification/ManagedServices.java
@@ -185,7 +185,7 @@
     }
 
     protected void addDefaultComponentOrPackage(String packageOrComponent) {
-        if (packageOrComponent != null) {
+        if (!TextUtils.isEmpty(packageOrComponent)) {
             synchronized (mDefaultsLock) {
                 ComponentName cn = ComponentName.unflattenFromString(packageOrComponent);
                 if (cn == null) {
diff --git a/services/core/java/com/android/server/notification/NotificationManagerService.java b/services/core/java/com/android/server/notification/NotificationManagerService.java
old mode 100644
new mode 100755
index d480cb6e..4457e9c
--- a/services/core/java/com/android/server/notification/NotificationManagerService.java
+++ b/services/core/java/com/android/server/notification/NotificationManagerService.java
@@ -49,7 +49,6 @@
 import static android.content.Context.BIND_AUTO_CREATE;
 import static android.content.Context.BIND_FOREGROUND_SERVICE;
 import static android.content.Context.BIND_NOT_PERCEPTIBLE;
-import static android.content.pm.ActivityInfo.DOCUMENT_LAUNCH_ALWAYS;
 import static android.content.pm.PackageManager.FEATURE_LEANBACK;
 import static android.content.pm.PackageManager.FEATURE_TELEVISION;
 import static android.content.pm.PackageManager.MATCH_ALL;
@@ -88,13 +87,11 @@
 import static android.service.notification.NotificationListenerService.TRIM_LIGHT;
 import static android.util.StatsLogInternal.BUBBLE_DEVELOPER_ERROR_REPORTED__ERROR__ACTIVITY_INFO_MISSING;
 import static android.util.StatsLogInternal.BUBBLE_DEVELOPER_ERROR_REPORTED__ERROR__ACTIVITY_INFO_NOT_RESIZABLE;
-import static android.util.StatsLogInternal.BUBBLE_DEVELOPER_ERROR_REPORTED__ERROR__DOCUMENT_LAUNCH_NOT_ALWAYS;
 import static android.view.WindowManager.LayoutParams.TYPE_TOAST;
 
 import static com.android.server.am.PendingIntentRecord.FLAG_ACTIVITY_SENDER;
 import static com.android.server.am.PendingIntentRecord.FLAG_BROADCAST_SENDER;
 import static com.android.server.am.PendingIntentRecord.FLAG_SERVICE_SENDER;
-import static com.android.server.notification.PreferencesHelper.DEFAULT_ALLOW_BUBBLE;
 import static com.android.server.utils.PriorityDump.PRIORITY_ARG;
 import static com.android.server.utils.PriorityDump.PRIORITY_ARG_CRITICAL;
 import static com.android.server.utils.PriorityDump.PRIORITY_ARG_NORMAL;
@@ -523,7 +520,6 @@
 
     }
 
-
     void loadDefaultApprovedServices(int userId) {
         String defaultListenerAccess = getContext().getResources().getString(
                 com.android.internal.R.string.config_defaultListenerAccessPackages);
@@ -531,6 +527,9 @@
             String[] listeners =
                     defaultListenerAccess.split(ManagedServices.ENABLED_SERVICES_SEPARATOR);
             for (int i = 0; i < listeners.length; i++) {
+                if (TextUtils.isEmpty(listeners[i])) {
+                    continue;
+                }
                 ArraySet<ComponentName> approvedListeners =
                         mListeners.queryPackageForServices(listeners[i],
                                 MATCH_DIRECT_BOOT_AWARE
@@ -547,6 +546,9 @@
         if (defaultDndAccess != null) {
             String[] dnds = defaultDndAccess.split(ManagedServices.ENABLED_SERVICES_SEPARATOR);
             for (int i = 0; i < dnds.length; i++) {
+                if (TextUtils.isEmpty(dnds[i])) {
+                    continue;
+                }
                 mConditionProviders.addDefaultComponentOrPackage(dnds[i]);
             }
         }
@@ -565,12 +567,14 @@
                 .split(ManagedServices.ENABLED_SERVICES_SEPARATOR)));
         for (int i = 0; i < assistants.size(); i++) {
             String cnString = assistants.valueAt(i);
+            if (TextUtils.isEmpty(cnString)) {
+                continue;
+            }
             mAssistants.addDefaultComponentOrPackage(cnString);
         }
     }
 
     protected void allowDefaultApprovedServices(int userId) {
-
         ArraySet<ComponentName> defaultListeners = mListeners.getDefaultComponents();
         for (int i = 0; i < defaultListeners.size(); i++) {
             ComponentName cn = defaultListeners.valueAt(i);
@@ -595,6 +599,40 @@
         }
     }
 
+    /**
+     * This method will update the flags of the summary.
+     * It will set it to FLAG_ONGOING_EVENT if any of its group members
+     * has the same flag. It will delete the flag otherwise
+     * @param userId user id of the autogroup summary
+     * @param pkg package of the autogroup summary
+     * @param needsOngoingFlag true if the group has at least one ongoing notification
+     */
+    @GuardedBy("mNotificationLock")
+    protected void updateAutobundledSummaryFlags(int userId, String pkg, boolean needsOngoingFlag) {
+        ArrayMap<String, String> summaries = mAutobundledSummaries.get(userId);
+        if (summaries == null) {
+            return;
+        }
+        String summaryKey = summaries.get(pkg);
+        if (summaryKey == null) {
+            return;
+        }
+        NotificationRecord summary = mNotificationsByKey.get(summaryKey);
+        if (summary == null) {
+            return;
+        }
+        int oldFlags = summary.sbn.getNotification().flags;
+        if (needsOngoingFlag) {
+            summary.sbn.getNotification().flags |= FLAG_ONGOING_EVENT;
+        } else {
+            summary.sbn.getNotification().flags &= ~FLAG_ONGOING_EVENT;
+        }
+
+        if (summary.sbn.getNotification().flags != oldFlags) {
+            mHandler.post(new EnqueueNotificationRunnable(userId, summary));
+        }
+    }
+
     private void allowDndPackage(String packageName) {
         try {
             getBinderService().setNotificationPolicyAccessGranted(packageName, true);
@@ -1331,16 +1369,15 @@
                     uidList = new int[] {intent.getIntExtra(Intent.EXTRA_UID, -1)};
                 }
                 if (pkgList != null && (pkgList.length > 0)) {
-                    for (String pkgName : pkgList) {
-                        if (cancelNotifications) {
+                    if (cancelNotifications) {
+                        for (String pkgName : pkgList) {
                             cancelAllNotificationsInt(MY_UID, MY_PID, pkgName, null, 0, 0,
                                     !queryRestart, changeUserId, reason, null);
-                        } else if (hideNotifications) {
-                            hideNotificationsForPackages(pkgList);
-                        } else if (unhideNotifications) {
-                            unhideNotificationsForPackages(pkgList);
                         }
-
+                    } else if (hideNotifications) {
+                        hideNotificationsForPackages(pkgList);
+                    } else if (unhideNotifications) {
+                        unhideNotificationsForPackages(pkgList);
                     }
                 }
 
@@ -1429,10 +1466,8 @@
     private final class SettingsObserver extends ContentObserver {
         private final Uri NOTIFICATION_BADGING_URI
                 = Settings.Secure.getUriFor(Settings.Secure.NOTIFICATION_BADGING);
-        private final Uri NOTIFICATION_BUBBLES_URI_GLOBAL
+        private final Uri NOTIFICATION_BUBBLES_URI
                 = Settings.Global.getUriFor(Settings.Global.NOTIFICATION_BUBBLES);
-        private final Uri NOTIFICATION_BUBBLES_URI_SECURE
-                = Settings.Secure.getUriFor(Settings.Secure.NOTIFICATION_BUBBLES);
         private final Uri NOTIFICATION_LIGHT_PULSE_URI
                 = Settings.System.getUriFor(Settings.System.NOTIFICATION_LIGHT_PULSE);
         private final Uri NOTIFICATION_RATE_LIMIT_URI
@@ -1450,9 +1485,7 @@
                     false, this, UserHandle.USER_ALL);
             resolver.registerContentObserver(NOTIFICATION_RATE_LIMIT_URI,
                     false, this, UserHandle.USER_ALL);
-            resolver.registerContentObserver(NOTIFICATION_BUBBLES_URI_GLOBAL,
-                    false, this, UserHandle.USER_ALL);
-            resolver.registerContentObserver(NOTIFICATION_BUBBLES_URI_SECURE,
+            resolver.registerContentObserver(NOTIFICATION_BUBBLES_URI,
                     false, this, UserHandle.USER_ALL);
             update(null);
         }
@@ -1479,41 +1512,9 @@
             if (uri == null || NOTIFICATION_BADGING_URI.equals(uri)) {
                 mPreferencesHelper.updateBadgingEnabled();
             }
-            // In QPR we moved the setting to Global rather than Secure so that the setting
-            // applied to work profiles. Unfortunately we need to maintain both to pass CTS without
-            // a change to CTS outside of a normal letter release.
-            if (uri == null || NOTIFICATION_BUBBLES_URI_GLOBAL.equals(uri)) {
-                syncBubbleSettings(resolver, NOTIFICATION_BUBBLES_URI_GLOBAL);
+            if (uri == null || NOTIFICATION_BUBBLES_URI.equals(uri)) {
                 mPreferencesHelper.updateBubblesEnabled();
             }
-            if (NOTIFICATION_BUBBLES_URI_SECURE.equals(uri)) {
-                syncBubbleSettings(resolver, NOTIFICATION_BUBBLES_URI_SECURE);
-            }
-        }
-
-        private void syncBubbleSettings(ContentResolver resolver, Uri settingToFollow) {
-            boolean followSecureSetting = settingToFollow.equals(NOTIFICATION_BUBBLES_URI_SECURE);
-
-            int secureSettingValue = Settings.Secure.getInt(resolver,
-                    Settings.Secure.NOTIFICATION_BUBBLES, DEFAULT_ALLOW_BUBBLE ? 1 : 0);
-            int globalSettingValue = Settings.Global.getInt(resolver,
-                    Settings.Global.NOTIFICATION_BUBBLES, DEFAULT_ALLOW_BUBBLE ? 1 : 0);
-
-            if (globalSettingValue == secureSettingValue) {
-                return;
-            }
-
-            if (followSecureSetting) {
-                // Global => secure
-                Settings.Global.putInt(resolver,
-                        Settings.Global.NOTIFICATION_BUBBLES,
-                        secureSettingValue);
-            } else {
-                // Secure => Global
-                Settings.Secure.putInt(resolver,
-                        Settings.Secure.NOTIFICATION_BADGING,
-                        globalSettingValue);
-            }
         }
     }
 
@@ -1948,7 +1949,6 @@
                 });
     }
 
-
     private GroupHelper getGroupHelper() {
         mAutoGroupAtCount =
                 getContext().getResources().getInteger(R.integer.config_autoGroupAtCount);
@@ -1978,6 +1978,16 @@
                     clearAutogroupSummaryLocked(userId, pkg);
                 }
             }
+
+            @Override
+            public void updateAutogroupSummary(String key, boolean needsOngoingFlag) {
+                synchronized (mNotificationLock) {
+                    NotificationRecord r = mNotificationsByKey.get(key);
+                    if (r == null) return;
+                    updateAutobundledSummaryFlags(r.getUser().getIdentifier(),
+                            r.sbn.getPackageName(), needsOngoingFlag);
+                }
+            }
         });
     }
 
@@ -5045,12 +5055,13 @@
         final int contentViewSize = contentView.estimateMemoryUsage();
         if (contentViewSize > mWarnRemoteViewsSizeBytes
                 && contentViewSize < mStripRemoteViewsSizeBytes) {
-            Slog.w(TAG, "RemoteViews too large on tag: " + tag + " id: " + id
+            Slog.w(TAG, "RemoteViews too large on pkg: " + pkg + " tag: " + tag + " id: " + id
                     + " this might be stripped in a future release");
         }
         if (contentViewSize >= mStripRemoteViewsSizeBytes) {
             mUsageStats.registerImageRemoved(pkg);
-            Slog.w(TAG, "Removed too large RemoteViews on tag: " + tag + " id: " + id);
+            Slog.w(TAG,
+                    "Removed too large RemoteViews on pkg: " + pkg + " tag: " + tag + " id: " + id);
             return true;
         }
         return false;
@@ -5238,18 +5249,6 @@
                     + intent);
             return false;
         }
-        if (info.documentLaunchMode != DOCUMENT_LAUNCH_ALWAYS) {
-            StatsLog.write(StatsLog.BUBBLE_DEVELOPER_ERROR_REPORTED, packageName,
-                    BUBBLE_DEVELOPER_ERROR_REPORTED__ERROR__DOCUMENT_LAUNCH_NOT_ALWAYS);
-            Log.w(TAG, "Unable to send as bubble -- activity is not documentLaunchMode=always "
-                    + "for intent: " + intent);
-            return false;
-        }
-        if ((info.flags & ActivityInfo.FLAG_ALLOW_EMBEDDED) == 0) {
-            Log.w(TAG, "Unable to send as bubble -- activity is not embeddable for intent: "
-                    + intent);
-            return false;
-        }
         return true;
     }
 
@@ -5792,6 +5791,10 @@
                                             n, hasAutoGroupSummaryLocked(n));
                                 }
                             });
+                        } else if (oldSbn != null) {
+                            final NotificationRecord finalRecord = r;
+                            mHandler.post(() -> mGroupHelper.onNotificationUpdated(
+                                    finalRecord.sbn, hasAutoGroupSummaryLocked(n)));
                         }
                     } else {
                         Slog.e(TAG, "Not posting notification without small icon: " + notification);
diff --git a/services/core/java/com/android/server/om/OverlayManagerService.java b/services/core/java/com/android/server/om/OverlayManagerService.java
index 83bea9d..5f3e503 100644
--- a/services/core/java/com/android/server/om/OverlayManagerService.java
+++ b/services/core/java/com/android/server/om/OverlayManagerService.java
@@ -17,11 +17,13 @@
 package com.android.server.om;
 
 import static android.app.AppGlobals.getPackageManager;
+import static android.content.Intent.ACTION_OVERLAY_CHANGED;
 import static android.content.Intent.ACTION_PACKAGE_ADDED;
 import static android.content.Intent.ACTION_PACKAGE_CHANGED;
 import static android.content.Intent.ACTION_PACKAGE_REMOVED;
 import static android.content.Intent.ACTION_USER_ADDED;
 import static android.content.Intent.ACTION_USER_REMOVED;
+import static android.content.Intent.EXTRA_REASON;
 import static android.content.pm.PackageManager.SIGNATURE_MATCH;
 import static android.os.Trace.TRACE_TAG_RRO;
 import static android.os.Trace.traceBegin;
@@ -356,7 +358,11 @@
                     }
                     break;
                 case ACTION_PACKAGE_CHANGED:
-                    onPackageChanged(packageName, userIds);
+                    // ignore the intent if it was sent by the package manager as a result of the
+                    // overlay manager having sent ACTION_OVERLAY_CHANGED
+                    if (!ACTION_OVERLAY_CHANGED.equals(intent.getStringExtra(EXTRA_REASON))) {
+                        onPackageChanged(packageName, userIds);
+                    }
                     break;
                 case ACTION_PACKAGE_REMOVED:
                     if (replacing) {
@@ -738,6 +744,25 @@
         }
 
         @Override
+        public void invalidateCachesForOverlay(@Nullable String packageName, int userId)
+                throws RemoteException {
+            if (packageName == null) {
+                return;
+            }
+
+            enforceChangeOverlayPackagesPermission("invalidateCachesForOverlay");
+            userId = handleIncomingUser(userId, "invalidateCachesForOverlay");
+            final long ident = Binder.clearCallingIdentity();
+            try {
+                synchronized (mLock) {
+                    mImpl.removeIdmapForOverlay(packageName, userId);
+                }
+            } finally {
+                Binder.restoreCallingIdentity(ident);
+            }
+        }
+
+        @Override
         public void onShellCommand(@NonNull final FileDescriptor in,
                 @NonNull final FileDescriptor out, @NonNull final FileDescriptor err,
                 @NonNull final String[] args, @NonNull final ShellCallback callback,
@@ -866,7 +891,7 @@
             FgThread.getHandler().post(() -> {
                 updateAssets(userId, targetPackageName);
 
-                final Intent intent = new Intent(Intent.ACTION_OVERLAY_CHANGED,
+                final Intent intent = new Intent(ACTION_OVERLAY_CHANGED,
                         Uri.fromParts("package", targetPackageName, null));
                 intent.setFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT);
 
diff --git a/services/core/java/com/android/server/om/OverlayManagerServiceImpl.java b/services/core/java/com/android/server/om/OverlayManagerServiceImpl.java
index 934511b..019c952 100644
--- a/services/core/java/com/android/server/om/OverlayManagerServiceImpl.java
+++ b/services/core/java/com/android/server/om/OverlayManagerServiceImpl.java
@@ -651,6 +651,11 @@
         return mDefaultOverlays;
     }
 
+    void removeIdmapForOverlay(String packageName, int userId) {
+        final OverlayInfo oi = mSettings.getOverlayInfo(packageName, userId);
+        removeIdmapIfPossible(oi);
+    }
+
     List<String> getEnabledOverlayPackageNames(@NonNull final String targetPackageName,
             final int userId) {
         final List<OverlayInfo> overlays = mSettings.getOverlaysForTarget(targetPackageName,
diff --git a/services/core/java/com/android/server/os/SchedulingPolicyService.java b/services/core/java/com/android/server/os/SchedulingPolicyService.java
index 2371b04..c3ed7d7 100644
--- a/services/core/java/com/android/server/os/SchedulingPolicyService.java
+++ b/services/core/java/com/android/server/os/SchedulingPolicyService.java
@@ -21,7 +21,6 @@
 import android.os.IBinder;
 import android.os.ISchedulingPolicyService;
 import android.os.Process;
-import android.os.RemoteException;
 import android.util.Log;
 
 import com.android.server.SystemServerInitThreadPool;
@@ -64,7 +63,7 @@
         // (Note that if mediaserver thinks we're in boosted state before the crash,
         // the state could go out of sync temporarily until mediaserver enables/disable
         // boost next time, but this won't be a big issue.)
-        SystemServerInitThreadPool.get().submit(() -> {
+        SystemServerInitThreadPool.submit(() -> {
             synchronized (mDeathRecipient) {
                 // only do this if we haven't already got a request to boost.
                 if (mBoostedPid == -1) {
diff --git a/services/core/java/com/android/server/pm/AppsFilter.java b/services/core/java/com/android/server/pm/AppsFilter.java
index 61ea84f..05b6168 100644
--- a/services/core/java/com/android/server/pm/AppsFilter.java
+++ b/services/core/java/com/android/server/pm/AppsFilter.java
@@ -41,7 +41,7 @@
 import com.android.internal.R;
 import com.android.internal.annotations.VisibleForTesting;
 import com.android.server.FgThread;
-import com.android.server.compat.PlatformCompat;
+import com.android.server.compat.CompatConfig;
 
 import java.io.PrintWriter;
 import java.util.ArrayList;
@@ -131,24 +131,22 @@
 
     private static class FeatureConfigImpl implements FeatureConfig {
         private static final String FILTERING_ENABLED_NAME = "package_query_filtering_enabled";
-        private final PackageManagerService.Injector mInjector;
         private volatile boolean mFeatureEnabled = true;
+        private CompatConfig mCompatibility;
 
         private FeatureConfigImpl(PackageManagerService.Injector injector) {
-            mInjector = injector;
+            mCompatibility = injector.getCompatibility();
         }
 
         @Override
         public void onSystemReady() {
             mFeatureEnabled = DeviceConfig.getBoolean(
-                    NAMESPACE_PACKAGE_MANAGER_SERVICE, FILTERING_ENABLED_NAME,
-                    true);
+                    NAMESPACE_PACKAGE_MANAGER_SERVICE, FILTERING_ENABLED_NAME, true);
             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, true);
                         }
                     });
         }
@@ -160,12 +158,7 @@
 
         @Override
         public boolean packageIsEnabled(PackageParser.Package pkg) {
-            final PlatformCompat compatibility = mInjector.getCompatibility();
-            if (compatibility == null) {
-                Slog.wtf(TAG, "PlatformCompat is null");
-                return mFeatureEnabled;
-            }
-            return compatibility.isChangeEnabled(
+            return mCompatibility.isChangeEnabled(
                     PackageManager.FILTER_APPLICATION_QUERY, pkg.applicationInfo);
         }
     }
@@ -202,19 +195,19 @@
             return false;
         }
         for (Intent intent : querying.mQueriesIntents) {
-            if (matches(intent, potentialTarget.providers, potentialTarget.activities,
-                    potentialTarget.services, potentialTarget.receivers)) {
+            if (matches(intent, potentialTarget)) {
                 return true;
             }
         }
         return false;
     }
 
-    private static boolean matches(Intent intent,
-            ArrayList<PackageParser.Provider> providerList,
-            ArrayList<? extends Component<? extends IntentInfo>>... componentLists) {
-        for (int p = providerList.size() - 1; p >= 0; p--) {
-            PackageParser.Provider provider = providerList.get(p);
+    private static boolean matches(Intent intent, PackageParser.Package potentialTarget) {
+        for (int p = potentialTarget.providers.size() - 1; p >= 0; p--) {
+            PackageParser.Provider provider = potentialTarget.providers.get(p);
+            if (!provider.info.exported) {
+                continue;
+            }
             final ProviderInfo providerInfo = provider.info;
             final Uri data = intent.getData();
             if ("content".equalsIgnoreCase(intent.getScheme())
@@ -223,19 +216,44 @@
                 return true;
             }
         }
+        for (int s = potentialTarget.services.size() - 1; s >= 0; s--) {
+            PackageParser.Service service = potentialTarget.services.get(s);
+            if (!service.info.exported) {
+                continue;
+            }
+            if (matchesAnyFilter(intent, service)) {
+                return true;
+            }
+        }
+        for (int a = potentialTarget.activities.size() - 1; a >= 0; a--) {
+            PackageParser.Activity activity = potentialTarget.activities.get(a);
+            if (!activity.info.exported) {
+                continue;
+            }
+            if (matchesAnyFilter(intent, activity)) {
+                return true;
+            }
+        }
+        for (int r = potentialTarget.receivers.size() - 1; r >= 0; r--) {
+            PackageParser.Activity receiver = potentialTarget.receivers.get(r);
+            if (!receiver.info.exported) {
+                continue;
+            }
+            if (matchesAnyFilter(intent, receiver)) {
+                return true;
+            }
+        }
+        return false;
+    }
 
-        for (int l = componentLists.length - 1; l >= 0; l--) {
-            ArrayList<? extends Component<? extends IntentInfo>> components = componentLists[l];
-            for (int c = components.size() - 1; c >= 0; c--) {
-                Component<? extends IntentInfo> component = components.get(c);
-                ArrayList<? extends IntentInfo> intents = component.intents;
-                for (int i = intents.size() - 1; i >= 0; i--) {
-                    IntentFilter intentFilter = intents.get(i);
-                    if (intentFilter.match(intent.getAction(), intent.getType(), intent.getScheme(),
-                            intent.getData(), intent.getCategories(), "AppsFilter") > 0) {
-                        return true;
-                    }
-                }
+    private static boolean matchesAnyFilter(
+            Intent intent, Component<? extends IntentInfo> component) {
+        ArrayList<? extends IntentInfo> intents = component.intents;
+        for (int i = intents.size() - 1; i >= 0; i--) {
+            IntentFilter intentFilter = intents.get(i);
+            if (intentFilter.match(intent.getAction(), intent.getType(), intent.getScheme(),
+                    intent.getData(), intent.getCategories(), "AppsFilter") > 0) {
+                return true;
             }
         }
         return false;
diff --git a/services/core/java/com/android/server/pm/ComponentResolver.java b/services/core/java/com/android/server/pm/ComponentResolver.java
index 8facce1..976cdfb 100644
--- a/services/core/java/com/android/server/pm/ComponentResolver.java
+++ b/services/core/java/com/android/server/pm/ComponentResolver.java
@@ -23,6 +23,7 @@
 import static com.android.server.pm.PackageManagerService.DEBUG_REMOVE;
 import static com.android.server.pm.PackageManagerService.fixProcessName;
 
+import android.annotation.Nullable;
 import android.content.ComponentName;
 import android.content.Intent;
 import android.content.IntentFilter;
@@ -219,12 +220,14 @@
         }
     }
 
+    @Nullable
     List<ResolveInfo> queryActivities(Intent intent, String resolvedType, int flags, int userId) {
         synchronized (mLock) {
             return mActivities.queryIntent(intent, resolvedType, flags, userId);
         }
     }
 
+    @Nullable
     List<ResolveInfo> queryActivities(Intent intent, String resolvedType, int flags,
             List<PackageParser.Activity> activities, int userId) {
         synchronized (mLock) {
@@ -233,12 +236,14 @@
         }
     }
 
+    @Nullable
     List<ResolveInfo> queryProviders(Intent intent, String resolvedType, int flags, int userId) {
         synchronized (mLock) {
             return mProviders.queryIntent(intent, resolvedType, flags, userId);
         }
     }
 
+    @Nullable
     List<ResolveInfo> queryProviders(Intent intent, String resolvedType, int flags,
             List<PackageParser.Provider> providers, int userId) {
         synchronized (mLock) {
@@ -246,6 +251,7 @@
         }
     }
 
+    @Nullable
     List<ProviderInfo> queryProviders(String processName, String metaDataKey, int uid, int flags,
             int userId) {
         if (!sUserManager.exists(userId)) {
@@ -285,6 +291,7 @@
         return providerList;
     }
 
+    @Nullable
     ProviderInfo queryProvider(String authority, int flags, int userId) {
         synchronized (mLock) {
             final PackageParser.Provider p = mProvidersByAuthority.get(authority);
@@ -326,12 +333,14 @@
         }
     }
 
+    @Nullable
     List<ResolveInfo> queryReceivers(Intent intent, String resolvedType, int flags, int userId) {
         synchronized (mLock) {
             return mReceivers.queryIntent(intent, resolvedType, flags, userId);
         }
     }
 
+    @Nullable
     List<ResolveInfo> queryReceivers(Intent intent, String resolvedType, int flags,
             List<PackageParser.Activity> receivers, int userId) {
         synchronized (mLock) {
@@ -339,12 +348,14 @@
         }
     }
 
+    @Nullable
     List<ResolveInfo> queryServices(Intent intent, String resolvedType, int flags, int userId) {
         synchronized (mLock) {
             return mServices.queryIntent(intent, resolvedType, flags, userId);
         }
     }
 
+    @Nullable
     List<ResolveInfo> queryServices(Intent intent, String resolvedType, int flags,
             List<PackageParser.Service> services, int userId) {
         synchronized (mLock) {
@@ -1355,6 +1366,7 @@
             return super.queryIntent(intent, resolvedType, defaultOnly, userId);
         }
 
+        @Nullable
         List<ResolveInfo> queryIntent(Intent intent, String resolvedType, int flags,
                 int userId) {
             if (!sUserManager.exists(userId)) {
@@ -1366,6 +1378,7 @@
                     userId);
         }
 
+        @Nullable
         List<ResolveInfo> queryIntentForPackage(Intent intent, String resolvedType,
                 int flags, List<PackageParser.Provider> packageProviders, int userId) {
             if (!sUserManager.exists(userId)) {
diff --git a/services/core/java/com/android/server/pm/PackageInstallerService.java b/services/core/java/com/android/server/pm/PackageInstallerService.java
index 8b24224..a7d4237 100644
--- a/services/core/java/com/android/server/pm/PackageInstallerService.java
+++ b/services/core/java/com/android/server/pm/PackageInstallerService.java
@@ -259,6 +259,10 @@
         // Don't hold mSessions lock when calling restoreSession, since it might trigger an APK
         // atomic install which needs to query sessions, which requires lock on mSessions.
         for (PackageInstallerSession session : stagedSessionsToRestore) {
+            if (mPm.isDeviceUpgrading()) {
+                session.setStagedSessionFailed(SessionInfo.STAGED_SESSION_ACTIVATION_FAILED,
+                        "Build fingerprint has changed");
+            }
             mStagingManager.restoreSession(session);
         }
         // Broadcasts are not sent while we restore sessions on boot, since no processes would be
diff --git a/core/java/android/content/pm/PackageList.java b/services/core/java/com/android/server/pm/PackageList.java
similarity index 96%
rename from core/java/android/content/pm/PackageList.java
rename to services/core/java/com/android/server/pm/PackageList.java
index e3eb2c5..60bc8a8 100644
--- a/core/java/android/content/pm/PackageList.java
+++ b/services/core/java/com/android/server/pm/PackageList.java
@@ -14,10 +14,11 @@
  * limitations under the License.
  */
 
-package android.content.pm;
+package com.android.server.pm;
 
 import android.annotation.NonNull;
 import android.annotation.Nullable;
+import android.content.pm.PackageManagerInternal;
 import android.content.pm.PackageManagerInternal.PackageListObserver;
 
 import com.android.server.LocalServices;
diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java
index 86340d4..67d0f62 100644
--- a/services/core/java/com/android/server/pm/PackageManagerService.java
+++ b/services/core/java/com/android/server/pm/PackageManagerService.java
@@ -162,7 +162,6 @@
 import android.content.pm.PackageInfo;
 import android.content.pm.PackageInfoLite;
 import android.content.pm.PackageInstaller;
-import android.content.pm.PackageList;
 import android.content.pm.PackageManager;
 import android.content.pm.PackageManager.LegacyPackageDeleteObserver;
 import android.content.pm.PackageManager.ModuleInfoFlags;
@@ -300,7 +299,7 @@
 import com.android.server.SystemConfig;
 import com.android.server.SystemServerInitThreadPool;
 import com.android.server.Watchdog;
-import com.android.server.compat.PlatformCompat;
+import com.android.server.compat.CompatConfig;
 import com.android.server.net.NetworkPolicyManagerInternal;
 import com.android.server.pm.Installer.InstallerException;
 import com.android.server.pm.Settings.DatabaseVersion;
@@ -835,7 +834,7 @@
         private final Singleton<StorageManager> mStorageManagerProducer;
         private final Singleton<AppOpsManager> mAppOpsManagerProducer;
         private final Singleton<AppsFilter> mAppsFilterProducer;
-        private final Singleton<PlatformCompat> mPlatformCompatProducer;
+        private final Singleton<CompatConfig> mPlatformCompatProducer;
 
         Injector(Context context, Object lock, Installer installer,
                 Object installLock, PackageAbiHelper abiHelper,
@@ -853,7 +852,7 @@
                 Producer<StorageManager> storageManagerProducer,
                 Producer<AppOpsManager> appOpsManagerProducer,
                 Producer<AppsFilter> appsFilterProducer,
-                Producer<PlatformCompat> platformCompatProducer) {
+                Producer<CompatConfig> platformCompatProducer) {
             mContext = context;
             mLock = lock;
             mInstaller = installer;
@@ -964,7 +963,7 @@
             return mAppsFilterProducer.get(this, mPackageManager);
         }
 
-        public PlatformCompat getCompatibility() {
+        public CompatConfig getCompatibility() {
             return mPlatformCompatProducer.get(this, mPackageManager);
         }
     }
@@ -1676,7 +1675,8 @@
                     }
                     // Send broadcasts
                     for (int i = 0; i < size; i++) {
-                        sendPackageChangedBroadcast(packages[i], true, components[i], uids[i]);
+                        sendPackageChangedBroadcast(packages[i], true, components[i], uids[i],
+                                null);
                     }
                     Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND);
                     break;
@@ -2164,7 +2164,7 @@
                     // send broadcast that all consumers of the static shared library have changed
                     sendPackageChangedBroadcast(pkg.packageName, false /*killFlag*/,
                             new ArrayList<>(Collections.singletonList(pkg.packageName)),
-                            pkg.applicationInfo.uid);
+                            pkg.applicationInfo.uid, null);
                 }
             }
 
@@ -2466,7 +2466,7 @@
                 new Injector.SystemServiceProducer<>(StorageManager.class),
                 new Injector.SystemServiceProducer<>(AppOpsManager.class),
                 (i, pm) -> AppsFilter.create(i),
-                (i, pm) -> (PlatformCompat) ServiceManager.getService("platform_compat"));
+                (i, pm) -> CompatConfig.get());
 
         PackageManagerService m = new PackageManagerService(injector, factoryTest, onlyCore);
         t.traceEnd(); // "create package manager"
@@ -3048,7 +3048,7 @@
 
             // Resolve protected action filters. Only the setup wizard is allowed to
             // have a high priority filter for these actions.
-            mSetupWizardPackage = getSetupWizardPackageName();
+            mSetupWizardPackage = getSetupWizardPackageNameImpl();
             mComponentResolver.fixProtectedFilterPriorities();
 
             mSystemTextClassifierPackage = getSystemTextClassifierPackageName();
@@ -3135,7 +3135,7 @@
             List<String> deferPackages = reconcileAppsDataLI(StorageManager.UUID_PRIVATE_INTERNAL,
                     UserHandle.USER_SYSTEM, storageFlags, true /* migrateAppData */,
                     true /* onlyCoreApps */);
-            mPrepareAppDataFuture = SystemServerInitThreadPool.get().submit(() -> {
+            mPrepareAppDataFuture = SystemServerInitThreadPool.submit(() -> {
                 TimingsTraceLog traceLog = new TimingsTraceLog("SystemServerTimingAsync",
                         Trace.TRACE_TAG_PACKAGE_MANAGER);
                 traceLog.traceBegin("AppDataFixup");
@@ -6976,7 +6976,7 @@
      * @param intent
      * @return A filtered list of resolved activities.
      */
-    private List<ResolveInfo> applyPostResolutionFilter(List<ResolveInfo> resolveInfos,
+    private List<ResolveInfo> applyPostResolutionFilter(@NonNull List<ResolveInfo> resolveInfos,
             String ephemeralPkgName, boolean allowDynamicSplits, int filterCallingUid,
             boolean resolveForStart, int userId, Intent intent) {
         final boolean blockInstant = intent.isWebIntent() && areWebInstantAppsDisabled(userId);
@@ -7633,6 +7633,9 @@
             if (pkgName == null) {
                 final List<ResolveInfo> result =
                         mComponentResolver.queryReceivers(intent, resolvedType, flags, userId);
+                if (result == null) {
+                    return Collections.emptyList();
+                }
                 return applyPostResolutionFilter(
                         result, instantAppPkgName, allowDynamicSplits, callingUid, false, userId,
                         intent);
@@ -7641,6 +7644,9 @@
             if (pkg != null) {
                 final List<ResolveInfo> result = mComponentResolver.queryReceivers(
                         intent, resolvedType, flags, pkg.receivers, userId);
+                if (result == null) {
+                    return Collections.emptyList();
+                }
                 return applyPostResolutionFilter(
                         result, instantAppPkgName, allowDynamicSplits, callingUid, false, userId,
                         intent);
@@ -7735,15 +7741,25 @@
         synchronized (mLock) {
             String pkgName = intent.getPackage();
             if (pkgName == null) {
+                final List<ResolveInfo> resolveInfos = mComponentResolver.queryServices(intent,
+                        resolvedType, flags, userId);
+                if (resolveInfos == null) {
+                    return Collections.emptyList();
+                }
                 return applyPostServiceResolutionFilter(
-                        mComponentResolver.queryServices(intent, resolvedType, flags, userId),
+                        resolveInfos,
                         instantAppPkgName);
             }
             final PackageParser.Package pkg = mPackages.get(pkgName);
             if (pkg != null) {
+                final List<ResolveInfo> resolveInfos = mComponentResolver.queryServices(intent,
+                        resolvedType, flags, pkg.services,
+                        userId);
+                if (resolveInfos == null) {
+                    return Collections.emptyList();
+                }
                 return applyPostServiceResolutionFilter(
-                        mComponentResolver.queryServices(intent, resolvedType, flags, pkg.services,
-                                userId),
+                        resolveInfos,
                         instantAppPkgName);
             }
             return Collections.emptyList();
@@ -7853,15 +7869,25 @@
         synchronized (mLock) {
             String pkgName = intent.getPackage();
             if (pkgName == null) {
+                final List<ResolveInfo> resolveInfos = mComponentResolver.queryProviders(intent,
+                        resolvedType, flags, userId);
+                if (resolveInfos == null) {
+                    return Collections.emptyList();
+                }
                 return applyPostContentProviderResolutionFilter(
-                        mComponentResolver.queryProviders(intent, resolvedType, flags, userId),
+                        resolveInfos,
                         instantAppPkgName);
             }
             final PackageParser.Package pkg = mPackages.get(pkgName);
             if (pkg != null) {
+                final List<ResolveInfo> resolveInfos = mComponentResolver.queryProviders(intent,
+                        resolvedType, flags,
+                        pkg.providers, userId);
+                if (resolveInfos == null) {
+                    return Collections.emptyList();
+                }
                 return applyPostContentProviderResolutionFilter(
-                        mComponentResolver.queryProviders(intent, resolvedType, flags,
-                                pkg.providers, userId),
+                        resolveInfos,
                         instantAppPkgName);
             }
             return Collections.emptyList();
@@ -13212,9 +13238,11 @@
      * @return verification timeout in milliseconds
      */
     private long getVerificationTimeout() {
-        return android.provider.Settings.Global.getLong(mContext.getContentResolver(),
-                android.provider.Settings.Global.PACKAGE_VERIFIER_TIMEOUT,
-                DEFAULT_VERIFICATION_TIMEOUT);
+        long timeout = Global.getLong(mContext.getContentResolver(),
+                Global.PACKAGE_VERIFIER_TIMEOUT, DEFAULT_VERIFICATION_TIMEOUT);
+        // The setting can be used to increase the timeout but not decrease it, since that is
+        // equivalent to disabling the verifier.
+        return Math.max(timeout, DEFAULT_VERIFICATION_TIMEOUT);
     }
 
     /**
@@ -13245,22 +13273,18 @@
             return false;
         }
 
-        boolean ensureVerifyAppsEnabled = isUserRestricted(userId, UserManager.ENSURE_VERIFY_APPS);
-
         // Check if installing from ADB
         if ((installFlags & PackageManager.INSTALL_FROM_ADB) != 0) {
             // Do not run verification in a test harness environment
             if (ActivityManager.isRunningInTestHarness()) {
                 return false;
             }
-            if (ensureVerifyAppsEnabled) {
+            if (isUserRestricted(userId, UserManager.ENSURE_VERIFY_APPS)) {
                 return true;
             }
             // Check if the developer does not want package verification for ADB installs
-            if (android.provider.Settings.Global.getInt(mContext.getContentResolver(),
-                    android.provider.Settings.Global.PACKAGE_VERIFIER_INCLUDE_ADB, 1) == 0) {
-                return false;
-            }
+            return Global.getInt(mContext.getContentResolver(),
+                    Global.PACKAGE_VERIFIER_INCLUDE_ADB, 1) != 0;
         } else {
             // only when not installed from ADB, skip verification for instant apps when
             // the installer and verifier are the same.
@@ -13278,14 +13302,8 @@
                     } catch (SecurityException ignore) { }
                 }
             }
-        }
-
-        if (ensureVerifyAppsEnabled) {
             return true;
         }
-
-        return android.provider.Settings.Global.getInt(mContext.getContentResolver(),
-                android.provider.Settings.Global.PACKAGE_VERIFIER_ENABLE, 1) == 1;
     }
 
     @Override
@@ -15078,19 +15096,6 @@
         return disabled;
     }
 
-    @GuardedBy("mLock")
-    private void setInstallerPackageNameLPw(PackageParser.Package pkg,
-            String installerPackageName) {
-        // Enable the parent package
-        mSettings.setInstallerPackageName(pkg.packageName, installerPackageName);
-        // Enable the child packages
-        final int childCount = (pkg.childPackages != null) ? pkg.childPackages.size() : 0;
-        for (int i = 0; i < childCount; i++) {
-            PackageParser.Package childPkg = pkg.childPackages.get(i);
-            mSettings.setInstallerPackageName(childPkg.packageName, installerPackageName);
-        }
-    }
-
     private void updateSettingsLI(PackageParser.Package newPackage, String installerPackageName,
             int[] allUsers, PackageInstalledInfo res, UserHandle user, int installReason) {
         // Update the parent package setting
@@ -17505,7 +17510,7 @@
                             continue;
                         }
                         List<VersionedPackage> libClientPackages = getPackagesUsingSharedLibraryLPr(
-                                libraryInfo, 0, currUserId);
+                                libraryInfo, MATCH_KNOWN_PACKAGES, currUserId);
                         if (!ArrayUtils.isEmpty(libClientPackages)) {
                             Slog.w(TAG, "Not removing package " + pkg.manifestPackageName
                                     + " hosting lib " + libraryInfo.getName() + " version "
@@ -19673,7 +19678,7 @@
                 set, comp, userId);
     }
 
-    private @Nullable String getSetupWizardPackageName() {
+    private @Nullable String getSetupWizardPackageNameImpl() {
         final Intent intent = new Intent(Intent.ACTION_MAIN);
         intent.addCategory(Intent.CATEGORY_SETUP_WIZARD);
 
@@ -19780,6 +19785,14 @@
         return systemCaptionsServiceComponentName.getPackageName();
     }
 
+    @Override
+    public String getSetupWizardPackageName() {
+        if (Binder.getCallingUid() != Process.SYSTEM_UID) {
+            throw new SecurityException("Non-system caller");
+        }
+        return mPmInternal.getSetupWizardPackageName();
+    }
+
     public String getIncidentReportApproverPackageName() {
         return mContext.getString(R.string.config_incidentReportApproverPackage);
     }
@@ -20027,7 +20040,7 @@
             if (sendNow) {
                 int packageUid = UserHandle.getUid(userId, pkgSetting.appId);
                 sendPackageChangedBroadcast(packageName,
-                        (flags&PackageManager.DONT_KILL_APP) != 0, components, packageUid);
+                        (flags & PackageManager.DONT_KILL_APP) != 0, components, packageUid, null);
             }
         } finally {
             Binder.restoreCallingIdentity(callingId);
@@ -20059,7 +20072,8 @@
     }
 
     private void sendPackageChangedBroadcast(String packageName,
-            boolean killFlag, ArrayList<String> componentNames, int packageUid) {
+            boolean killFlag, ArrayList<String> componentNames, int packageUid,
+            String reason) {
         if (DEBUG_INSTALL)
             Log.v(TAG, "Sending package changed: package=" + packageName + " components="
                     + componentNames);
@@ -20070,6 +20084,9 @@
         extras.putStringArray(Intent.EXTRA_CHANGED_COMPONENT_NAME_LIST, nameList);
         extras.putBoolean(Intent.EXTRA_DONT_KILL_APP, killFlag);
         extras.putInt(Intent.EXTRA_UID, packageUid);
+        if (reason != null) {
+            extras.putString(Intent.EXTRA_REASON, reason);
+        }
         // If this is not reporting a change of the overall package, then only send it
         // to registered receivers.  We don't want to launch a swath of apps for every
         // little component state change.
@@ -20317,6 +20334,34 @@
             }, new IntentFilter(Intent.ACTION_BOOT_COMPLETED));
         }
 
+        IntentFilter overlayFilter = new IntentFilter(Intent.ACTION_OVERLAY_CHANGED);
+        overlayFilter.addDataScheme("package");
+        mContext.registerReceiver(new BroadcastReceiver() {
+            @Override
+            public void onReceive(Context context, Intent intent) {
+                if (intent == null) {
+                    return;
+                }
+                Uri data = intent.getData();
+                if (data == null) {
+                    return;
+                }
+                String packageName = data.getSchemeSpecificPart();
+                if (packageName == null) {
+                    return;
+                }
+                PackageParser.Package pkg = mPackages.get(packageName);
+                if (pkg == null) {
+                    return;
+                }
+                sendPackageChangedBroadcast(pkg.packageName,
+                        false /* killFlag */,
+                        new ArrayList<>(Collections.singletonList(pkg.packageName)),
+                        pkg.applicationInfo.uid,
+                        Intent.ACTION_OVERLAY_CHANGED);
+            }
+        }, overlayFilter);
+
         mModuleInfoProvider.systemReady();
 
         // Installer service might attempt to install some packages that have been staged for
diff --git a/services/core/java/com/android/server/pm/PackageManagerShellCommand.java b/services/core/java/com/android/server/pm/PackageManagerShellCommand.java
index 6435d9b..1c1c947 100644
--- a/services/core/java/com/android/server/pm/PackageManagerShellCommand.java
+++ b/services/core/java/com/android/server/pm/PackageManagerShellCommand.java
@@ -2415,6 +2415,7 @@
         int userId = -1;
         int flags = 0;
         String opt;
+        boolean preCreateOnly = false;
         while ((opt = getNextOption()) != null) {
             if ("--profileOf".equals(opt)) {
                 userId = UserHandle.parseUserArg(getNextArgRequired());
@@ -2428,6 +2429,8 @@
                 flags |= UserInfo.FLAG_GUEST;
             } else if ("--demo".equals(opt)) {
                 flags |= UserInfo.FLAG_DEMO;
+            } else if ("--pre-create-only".equals(opt)) {
+                preCreateOnly = true;
             } else {
                 getErrPrintWriter().println("Error: unknown option " + opt);
                 return 1;
@@ -2451,7 +2454,7 @@
             accm.addSharedAccountsFromParentUser(parentUserId, userId,
                     (Process.myUid() == Process.ROOT_UID) ? "root" : "com.android.shell");
         } else if (userId < 0) {
-            info = um.createUser(name, flags);
+            info = preCreateOnly ? um.preCreateUser(flags) : um.createUser(name, flags);
         } else {
             info = um.createProfileForUser(name, flags, userId, null);
         }
@@ -3364,8 +3367,11 @@
         pw.println("  trim-caches DESIRED_FREE_SPACE [internal|UUID]");
         pw.println("    Trim cache files to reach the given free space.");
         pw.println("");
+        pw.println("  list users");
+        pw.println("    Lists the current users.");
+        pw.println("");
         pw.println("  create-user [--profileOf USER_ID] [--managed] [--restricted] [--ephemeral]");
-        pw.println("      [--guest] USER_NAME");
+        pw.println("      [--guest] [--pre-create-only] USER_NAME");
         pw.println("    Create a new user with the given USER_NAME, printing the new user identifier");
         pw.println("    of the user.");
         pw.println("");
diff --git a/services/core/java/com/android/server/pm/ShortcutService.java b/services/core/java/com/android/server/pm/ShortcutService.java
index ebba128..8253b392 100644
--- a/services/core/java/com/android/server/pm/ShortcutService.java
+++ b/services/core/java/com/android/server/pm/ShortcutService.java
@@ -1200,12 +1200,20 @@
         return mUsers.get(userId) != null;
     }
 
+    private int mLastLockedUser = -1;
+
     /** Return the per-user state. */
     @GuardedBy("mLock")
     @NonNull
     ShortcutUser getUserShortcutsLocked(@UserIdInt int userId) {
         if (!isUserUnlockedL(userId)) {
-            wtf("User still locked");
+            // Only do wtf once for each user. (until the user is unlocked)
+            if (userId != mLastLockedUser) {
+                wtf("User still locked");
+                mLastLockedUser = userId;
+            }
+        } else {
+            mLastLockedUser = -1;
         }
 
         ShortcutUser userPackages = mUsers.get(userId);
diff --git a/services/core/java/com/android/server/pm/UserManagerService.java b/services/core/java/com/android/server/pm/UserManagerService.java
index dace598..95baa01 100644
--- a/services/core/java/com/android/server/pm/UserManagerService.java
+++ b/services/core/java/com/android/server/pm/UserManagerService.java
@@ -41,6 +41,7 @@
 import android.content.pm.PackageManager.NameNotFoundException;
 import android.content.pm.ShortcutServiceInternal;
 import android.content.pm.UserInfo;
+import android.content.pm.UserInfo.UserInfoFlag;
 import android.content.res.Resources;
 import android.graphics.Bitmap;
 import android.os.Binder;
@@ -158,6 +159,7 @@
     private static final String ATTR_SERIAL_NO = "serialNumber";
     private static final String ATTR_NEXT_SERIAL_NO = "nextSerialNumber";
     private static final String ATTR_PARTIAL = "partial";
+    private static final String ATTR_PRE_CREATED = "preCreated";
     private static final String ATTR_GUEST_TO_REMOVE = "guestToRemove";
     private static final String ATTR_USER_VERSION = "version";
     private static final String ATTR_PROFILE_GROUP_ID = "profileGroupId";
@@ -207,7 +209,8 @@
             | UserInfo.FLAG_DEMO;
 
     @VisibleForTesting
-    static final int MIN_USER_ID = 10;
+    static final int MIN_USER_ID = UserHandle.MIN_SECONDARY_USER_ID;
+
     // We need to keep process uid within Integer.MAX_VALUE.
     @VisibleForTesting
     static final int MAX_USER_ID = Integer.MAX_VALUE / UserHandle.PER_USER_RANGE;
@@ -597,7 +600,8 @@
             final int userSize = mUsers.size();
             for (int i = 0; i < userSize; i++) {
                 UserInfo ui = mUsers.valueAt(i).info;
-                if ((ui.partial || ui.guestToRemove || ui.isEphemeral()) && i != 0) {
+                if ((ui.partial || ui.guestToRemove || (ui.isEphemeral() && !ui.preCreated))
+                        && i != 0) {
                     partials.add(ui);
                     addRemovingUserIdLocked(ui.id);
                     ui.partial = true;
@@ -660,20 +664,25 @@
         return null;
     }
 
-    @Override
     public @NonNull List<UserInfo> getUsers(boolean excludeDying) {
+        return getUsers(/*excludePartial= */ true, excludeDying, /* excludePreCreated= */ true);
+    }
+
+    @Override
+    public @NonNull List<UserInfo> getUsers(boolean excludePartial, boolean excludeDying,
+            boolean excludePreCreated) {
         checkManageOrCreateUsersPermission("query users");
         synchronized (mUsersLock) {
             ArrayList<UserInfo> users = new ArrayList<UserInfo>(mUsers.size());
             final int userSize = mUsers.size();
             for (int i = 0; i < userSize; i++) {
                 UserInfo ui = mUsers.valueAt(i).info;
-                if (ui.partial) {
+                if ((excludePartial && ui.partial)
+                        || (excludeDying && mRemovingUserIds.get(ui.id))
+                        || (excludePreCreated && ui.preCreated)) {
                     continue;
                 }
-                if (!excludeDying || !mRemovingUserIds.get(ui.id)) {
-                    users.add(userWithName(ui));
-                }
+                users.add(userWithName(ui));
             }
             return users;
         }
@@ -1196,7 +1205,7 @@
 
     private void checkManageOrInteractPermIfCallerInOtherProfileGroup(@UserIdInt int userId,
             String name) {
-        int callingUserId = UserHandle.getCallingUserId();
+        final int callingUserId = UserHandle.getCallingUserId();
         if (callingUserId == userId || isSameProfileGroupNoChecks(callingUserId, userId) ||
                 hasManageUsersPermission()) {
             return;
@@ -1210,7 +1219,7 @@
 
     @Override
     public boolean isDemoUser(@UserIdInt int userId) {
-        int callingUserId = UserHandle.getCallingUserId();
+        final int callingUserId = UserHandle.getCallingUserId();
         if (callingUserId != userId && !hasManageUsersPermission()) {
             throw new SecurityException("You need MANAGE_USERS permission to query if u=" + userId
                     + " is a demo user");
@@ -1222,6 +1231,19 @@
     }
 
     @Override
+    public boolean isPreCreated(@UserIdInt int userId) {
+        final int callingUserId = UserHandle.getCallingUserId();
+        if (callingUserId != userId && !hasManageUsersPermission()) {
+            throw new SecurityException("You need MANAGE_USERS permission to query if u=" + userId
+                    + " is pre-created");
+        }
+        synchronized (mUsersLock) {
+            UserInfo userInfo = getUserInfoLU(userId);
+            return userInfo != null && userInfo.preCreated;
+        }
+    }
+
+    @Override
     public boolean isRestricted() {
         synchronized (mUsersLock) {
             return getUserInfoLU(UserHandle.getCallingUserId()).isRestricted();
@@ -1871,7 +1893,7 @@
         // Skip over users being removed
         for (int i = 0; i < totalUserCount; i++) {
             UserInfo user = mUsers.valueAt(i).info;
-            if (!mRemovingUserIds.get(user.id) && !user.isGuest()) {
+            if (!mRemovingUserIds.get(user.id) && !user.isGuest() && !user.preCreated) {
                 aliveUserCount++;
             }
         }
@@ -2362,6 +2384,9 @@
         if (userInfo.partial) {
             serializer.attribute(null, ATTR_PARTIAL, "true");
         }
+        if (userInfo.preCreated) {
+            serializer.attribute(null, ATTR_PRE_CREATED, "true");
+        }
         if (userInfo.guestToRemove) {
             serializer.attribute(null, ATTR_GUEST_TO_REMOVE, "true");
         }
@@ -2518,6 +2543,7 @@
         int profileBadge = 0;
         int restrictedProfileParentId = UserInfo.NO_PROFILE_GROUP_ID;
         boolean partial = false;
+        boolean preCreated = false;
         boolean guestToRemove = false;
         boolean persistSeedData = false;
         String seedAccountName = null;
@@ -2562,6 +2588,10 @@
             if ("true".equals(valueString)) {
                 partial = true;
             }
+            valueString = parser.getAttributeValue(null, ATTR_PRE_CREATED);
+            if ("true".equals(valueString)) {
+                preCreated = true;
+            }
             valueString = parser.getAttributeValue(null, ATTR_GUEST_TO_REMOVE);
             if ("true".equals(valueString)) {
                 guestToRemove = true;
@@ -2615,6 +2645,7 @@
         userInfo.lastLoggedInTime = lastLoggedInTime;
         userInfo.lastLoggedInFingerprint = lastLoggedInFingerprint;
         userInfo.partial = partial;
+        userInfo.preCreated = preCreated;
         userInfo.guestToRemove = guestToRemove;
         userInfo.profileGroupId = profileGroupId;
         userInfo.profileBadge = profileBadge;
@@ -2686,7 +2717,8 @@
     public UserInfo createProfileForUserEvenWhenDisallowed(String name, int flags,
             @UserIdInt int userId, String[] disallowedPackages) {
         checkManageOrCreateUsersPermission(flags);
-        return createUserInternalUnchecked(name, flags, userId, disallowedPackages);
+        return createUserInternalUnchecked(name, flags, userId, /* preCreate= */ false,
+                disallowedPackages);
     }
 
     @Override
@@ -2701,12 +2733,27 @@
         return createUserInternal(name, flags, UserHandle.USER_NULL);
     }
 
-    private UserInfo createUserInternal(String name, int flags, int parentId) {
+    @Override
+    public UserInfo preCreateUser(int flags) {
+        checkManageOrCreateUsersPermission(flags);
+
+        Preconditions.checkArgument(!UserInfo.isManagedProfile(flags),
+                "cannot pre-create managed profiles");
+
+        Slog.i(LOG_TAG, "Pre-creating user with flags " + UserInfo.flagsToString(flags));
+
+        return createUserInternalUnchecked(/* name= */ null, flags,
+                /* parentId= */ UserHandle.USER_NULL, /* preCreate= */ true,
+                /* disallowedPackages= */ null);
+    }
+
+    private UserInfo createUserInternal(@Nullable String name, @UserInfoFlag int flags,
+            @UserIdInt int parentId) {
         return createUserInternal(name, flags, parentId, null);
     }
 
-    private UserInfo createUserInternal(String name, int flags, int parentId,
-            String[] disallowedPackages) {
+    private UserInfo createUserInternal(@Nullable String name, @UserInfoFlag int flags,
+            @UserIdInt int parentId, @Nullable String[] disallowedPackages) {
         String restriction = ((flags & UserInfo.FLAG_MANAGED_PROFILE) != 0)
                 ? UserManager.DISALLOW_ADD_MANAGED_PROFILE
                 : UserManager.DISALLOW_ADD_USER;
@@ -2714,21 +2761,56 @@
             Log.w(LOG_TAG, "Cannot add user. " + restriction + " is enabled.");
             return null;
         }
-        return createUserInternalUnchecked(name, flags, parentId, disallowedPackages);
+        return createUserInternalUnchecked(name, flags, parentId, /* preCreate= */ false,
+                disallowedPackages);
     }
 
-    private UserInfo createUserInternalUnchecked(@Nullable String name, int flags,
-            int parentId, @Nullable String[] disallowedPackages) {
-        TimingsTraceAndSlog t = new TimingsTraceAndSlog();
-        t.traceBegin("createUser");
-        UserInfo userInfo =
-                createUserInternalUncheckedNoTracing(name, flags, parentId, disallowedPackages, t);
-        t.traceEnd();
-        return userInfo;
+    private UserInfo createUserInternalUnchecked(@Nullable String name, @UserInfoFlag int flags,
+            @UserIdInt int parentId, boolean preCreate,
+            @Nullable String[] disallowedPackages) {
+        final TimingsTraceAndSlog t = new TimingsTraceAndSlog();
+        t.traceBegin("createUser-" + flags);
+        try {
+            return createUserInternalUncheckedNoTracing(name, flags, parentId, preCreate,
+                disallowedPackages, t);
+        } finally {
+            t.traceEnd();
+        }
     }
 
-    private UserInfo createUserInternalUncheckedNoTracing(@Nullable String name, int flags,
-            int parentId, @Nullable String[] disallowedPackages, @NonNull TimingsTraceAndSlog t) {
+    private UserInfo createUserInternalUncheckedNoTracing(@Nullable String name,
+            @UserInfoFlag int flags, @UserIdInt int parentId, boolean preCreate,
+            @Nullable String[] disallowedPackages, @NonNull TimingsTraceAndSlog t) {
+
+        // First try to use a pre-created user (if available).
+        // NOTE: currently we don't support pre-created managed profiles
+        if (!preCreate && (parentId < 0 && !UserInfo.isManagedProfile(flags))) {
+            final UserData preCreatedUserData;
+            synchronized (mUsersLock) {
+                preCreatedUserData = getPreCreatedUserLU(flags);
+            }
+            if (preCreatedUserData != null) {
+                final UserInfo preCreatedUser = preCreatedUserData.info;
+                Log.i(LOG_TAG, "Reusing pre-created user " + preCreatedUser.id + " for flags + "
+                        + UserInfo.flagsToString(flags));
+                if (DBG) {
+                    Log.d(LOG_TAG, "pre-created user flags: "
+                            + UserInfo.flagsToString(preCreatedUser.flags)
+                            + " new-user flags: " + UserInfo.flagsToString(flags));
+                }
+                preCreatedUser.name = name;
+                preCreatedUser.preCreated = false;
+                preCreatedUser.creationTime = getCreationTime();
+
+                dispatchUserAddedIntent(preCreatedUser);
+
+                writeUserLP(preCreatedUserData);
+                writeUserListLP();
+
+                return preCreatedUser;
+            }
+        }
+
         DeviceStorageMonitorInternal dsm = LocalServices
                 .getService(DeviceStorageMonitorInternal.class);
         if (dsm.isMemoryLow()) {
@@ -2736,8 +2818,8 @@
             return null;
         }
 
-        final boolean isGuest = (flags & UserInfo.FLAG_GUEST) != 0;
-        final boolean isManagedProfile = (flags & UserInfo.FLAG_MANAGED_PROFILE) != 0;
+        final boolean isGuest = UserInfo.isGuest(flags);
+        final boolean isManagedProfile = UserInfo.isManagedProfile(flags);
         final boolean isRestricted = (flags & UserInfo.FLAG_RESTRICTED) != 0;
         final boolean isDemo = (flags & UserInfo.FLAG_DEMO) != 0;
         final long ident = Binder.clearCallingIdentity();
@@ -2758,8 +2840,8 @@
                     return null;
                 }
                 if (!isGuest && !isManagedProfile && !isDemo && isUserLimitReached()) {
-                    // If we're not adding a guest/demo user or a managed profile and the limit has
-                    // been reached, cannot add a user.
+                    // If we're not adding a guest/demo user or a managed profile,
+                    // and the limit has been reached, cannot add a user.
                     Log.e(LOG_TAG, "Cannot add user. Maximum user limit is reached.");
                     return null;
                 }
@@ -2794,8 +2876,7 @@
 
                 userId = getNextAvailableId();
                 Environment.getUserSystemDirectory(userId).mkdirs();
-                boolean ephemeralGuests = Resources.getSystem()
-                        .getBoolean(com.android.internal.R.bool.config_guestUserEphemeral);
+                boolean ephemeralGuests = areGuestUsersEphemeral();
 
                 synchronized (mUsersLock) {
                     // Add ephemeral flag to guests/users if required. Also inherit it from parent.
@@ -2806,9 +2887,9 @@
 
                     userInfo = new UserInfo(userId, name, null, flags);
                     userInfo.serialNumber = mNextSerialNumber++;
-                    long now = System.currentTimeMillis();
-                    userInfo.creationTime = (now > EPOCH_PLUS_30_YEARS) ? now : 0;
+                    userInfo.creationTime = getCreationTime();
                     userInfo.partial = true;
+                    userInfo.preCreated = preCreate;
                     userInfo.lastLoggedInFingerprint = Build.FINGERPRINT;
                     if (isManagedProfile && parentId != UserHandle.USER_NULL) {
                         userInfo.profileBadge = getFreeProfileBadgeLU(parentId);
@@ -2869,17 +2950,40 @@
 
             t.traceBegin("PM.onNewUserCreated");
             mPm.onNewUserCreated(userId);
-            t.traceEnd();
 
-            Intent addedIntent = new Intent(Intent.ACTION_USER_ADDED);
-            addedIntent.putExtra(Intent.EXTRA_USER_HANDLE, userId);
-            mContext.sendBroadcastAsUser(addedIntent, UserHandle.ALL,
-                    android.Manifest.permission.MANAGE_USERS);
-            MetricsLogger.count(mContext, isGuest ? TRON_GUEST_CREATED
-                    : (isDemo ? TRON_DEMO_CREATED : TRON_USER_CREATED), 1);
+            if (preCreate) {
+                // Must start user (which will be stopped right away, through
+                // UserController.finishUserUnlockedCompleted) so services can properly
+                // intialize it.
+                // TODO(b/140750212): in the long-term, we should add a onCreateUser() callback
+                // on SystemService instead.
+                Slog.i(LOG_TAG, "starting pre-created user " + userInfo.toFullString());
+                final IActivityManager am = ActivityManager.getService();
+                try {
+                    am.startUserInBackground(userId);
+                } catch (RemoteException e) {
+                    Slog.w(LOG_TAG, "could not start pre-created user " + userId, e);
+                }
+            } else {
+                dispatchUserAddedIntent(userInfo);
+            }
+
         } finally {
             Binder.restoreCallingIdentity(ident);
         }
+
+        // TODO(b/140750212): it's possible to reach "max users overflow" when the user is created
+        // "from scratch" (i.e., not from a pre-created user) and reaches the maximum number of
+        // users without counting the pre-created one. Then when the pre-created is converted, the
+        // "effective" number of max users is exceeds. Example:
+        // Max: 3 Current: 2 full (u0 and u10) + 1 pre-created (u11)
+        // Step 1: create(/* flags doesn't match u11 */): u12 is created, "effective max" is now 3
+        //         (u0, u10, u12) but "real" max is 4 (u0, u10, u11, u12)
+        // Step 2: create(/* flags match u11 */): u11 is converted, now "effective max" is also 4
+        //         (u0, u10, u11, u12)
+        // One way to avoid this issue is by removing a pre-created user from the pool when the
+        // "real" max exceeds the max here.
+
         return userInfo;
     }
 
@@ -2888,6 +2992,62 @@
         return mSystemPackageInstaller.installWhitelistedSystemPackages(isFirstBoot, isUpgrade);
     }
 
+    private long getCreationTime() {
+        final long now = System.currentTimeMillis();
+        return (now > EPOCH_PLUS_30_YEARS) ? now : 0;
+    }
+
+    private void dispatchUserAddedIntent(@NonNull UserInfo userInfo) {
+        Intent addedIntent = new Intent(Intent.ACTION_USER_ADDED);
+        addedIntent.putExtra(Intent.EXTRA_USER_HANDLE, userInfo.id);
+        mContext.sendBroadcastAsUser(addedIntent, UserHandle.ALL,
+                android.Manifest.permission.MANAGE_USERS);
+        MetricsLogger.count(mContext, userInfo.isGuest() ? TRON_GUEST_CREATED
+                : (userInfo.isDemo() ? TRON_DEMO_CREATED : TRON_USER_CREATED), 1);
+    }
+
+    private boolean areGuestUsersEphemeral() {
+        return Resources.getSystem()
+                .getBoolean(com.android.internal.R.bool.config_guestUserEphemeral);
+    }
+
+    /**
+     * Gets a pre-created user for the given flag.
+     *
+     * <p>Should be used only during user creation, so the pre-created user can be used (instead of
+     * creating and initializing a new user from scratch).
+     */
+    // TODO(b/140750212): add unit test
+    @GuardedBy("mUsersLock")
+    private @Nullable UserData getPreCreatedUserLU(@UserInfoFlag int flags) {
+        if (DBG) {
+            Slog.d(LOG_TAG, "getPreCreatedUser(): initialFlags= " + UserInfo.flagsToString(flags));
+        }
+        flags |= UserInfo.FLAG_FULL;
+        if (UserInfo.isGuest(flags) && areGuestUsersEphemeral()) {
+            flags |= UserInfo.FLAG_EPHEMERAL;
+        }
+        if (DBG) {
+            Slog.d(LOG_TAG, "getPreCreatedUser(): targetFlags= " + UserInfo.flagsToString(flags));
+        }
+        final int userSize = mUsers.size();
+        for (int i = 0; i < userSize; i++) {
+            final UserData user = mUsers.valueAt(i);
+            if (DBG) Slog.d(LOG_TAG, i + ":" + user.info.toFullString());
+            if (user.info.preCreated
+                    && (user.info.flags & ~UserInfo.FLAG_INITIALIZED) == flags) {
+                if (!user.info.isInitialized()) {
+                    Slog.w(LOG_TAG, "found pre-created user for flags "
+                            + "" + UserInfo.flagsToString(flags)
+                            + ", but it's not initialized yet: " + user.info.toFullString());
+                    continue;
+                }
+                return user;
+            }
+        }
+        return null;
+    }
+
     @VisibleForTesting
     UserData putUserInfo(UserInfo userInfo) {
         final UserData userData = new UserData();
@@ -3728,7 +3888,7 @@
         try {
             switch(cmd) {
                 case "list":
-                    return runList(pw);
+                    return runList(pw, shell);
                 default:
                     return shell.handleDefaultCommands(cmd);
             }
@@ -3738,17 +3898,58 @@
         return -1;
     }
 
-    private int runList(PrintWriter pw) throws RemoteException {
+    private int runList(PrintWriter pw, Shell shell) throws RemoteException {
+        boolean all = false;
+        boolean verbose = false;
+        String opt;
+        while ((opt = shell.getNextOption()) != null) {
+            switch (opt) {
+                case "-v":
+                    verbose = true;
+                    break;
+                case "--all":
+                    all = true;
+                    break;
+                default:
+                    pw.println("Invalid option: " + opt);
+                    return -1;
+            }
+        }
         final IActivityManager am = ActivityManager.getService();
-        final List<UserInfo> users = getUsers(false);
+        final List<UserInfo> users = getUsers(/* excludePartial= */ !all,
+                /* excludingDying=*/ false, /* excludePreCreated= */ !all);
         if (users == null) {
             pw.println("Error: couldn't get users");
             return 1;
         } else {
-            pw.println("Users:");
-            for (int i = 0; i < users.size(); i++) {
-                String running = am.isUserRunning(users.get(i).id, 0) ? " running" : "";
-                pw.println("\t" + users.get(i).toString() + running);
+            final int size = users.size();
+            int currentUser = UserHandle.USER_NULL;
+            if (verbose) {
+                pw.printf("%d users:\n\n", size);
+                currentUser = am.getCurrentUser().id;
+            } else {
+                // NOTE: the standard "list users" command is used by integration tests and
+                // hence should not be changed. If you need to add more info, use the
+                // verbose option.
+                pw.println("Users:");
+            }
+            for (int i = 0; i < size; i++) {
+                final UserInfo user = users.get(i);
+                final boolean running = am.isUserRunning(user.id, 0);
+                final boolean current = user.id == currentUser;
+                if (verbose) {
+                    pw.printf("%d: id=%d, name=%s, flags=%s%s%s%s%s\n", i, user.id, user.name,
+                            UserInfo.flagsToString(user.flags),
+                            running ? " (running)" : "",
+                            user.partial ? " (partial)" : "",
+                            user.preCreated ? " (pre-created)" : "",
+                            current ? " (current)" : "");
+                } else {
+                    // NOTE: the standard "list users" command is used by integration tests and
+                    // hence should not be changed. If you need to add more info, use the
+                    // verbose option.
+                    pw.printf("\t%s%s\n", user, running ? " running" : "");
+                }
             }
             return 0;
         }
@@ -3785,6 +3986,9 @@
                     if (userInfo.partial) {
                         pw.print(" <partial>");
                     }
+                    if (userInfo.preCreated) {
+                        pw.print(" <pre-created>");
+                    }
                     pw.println();
                     pw.print("    Flags: "); pw.print(userInfo.flags); pw.print(" (");
                     pw.print(UserInfo.flagsToString(userInfo.flags)); pw.println(")");
@@ -3867,10 +4071,10 @@
 
         // Dump some capabilities
         pw.println();
-        pw.println("  Max users: " + UserManager.getMaxSupportedUsers());
+        pw.print("  Max users: " + UserManager.getMaxSupportedUsers());
+        pw.println(" (limit reached: " + isUserLimitReached() + ")");
         pw.println("  Supports switchable users: " + UserManager.supportsMultipleUsers());
-        pw.println("  All guests ephemeral: " + Resources.getSystem().getBoolean(
-                com.android.internal.R.bool.config_guestUserEphemeral));
+        pw.println("  All guests ephemeral: " + areGuestUsersEphemeral());
         pw.println("  Is split-system user: " + UserManager.isSplitSystemUser());
         pw.println("  Is headless-system mode: " + UserManager.isHeadlessSystemUserMode());
         pw.println("  User version: " + mUserVersion);
@@ -4076,7 +4280,7 @@
         public UserInfo createUserEvenWhenDisallowed(String name, int flags,
                 String[] disallowedPackages) {
             UserInfo user = createUserInternalUnchecked(name, flags, UserHandle.USER_NULL,
-                    disallowedPackages);
+                    /* preCreated= */ false, disallowedPackages);
             // Keep this in sync with UserManager.createUser
             if (user != null && !user.isAdmin() && !user.isDemo()) {
                 setUserRestriction(UserManager.DISALLOW_SMS, true, user.id);
@@ -4270,7 +4474,7 @@
             pw.println("  help");
             pw.println("    Print this help text.");
             pw.println("");
-            pw.println("  list");
+            pw.println("  list [-v] [-all]");
             pw.println("    Prints all users on the system.");
         }
     }
diff --git a/services/core/java/com/android/server/pm/UserSystemPackageInstaller.java b/services/core/java/com/android/server/pm/UserSystemPackageInstaller.java
index 036d1e8..323c957 100644
--- a/services/core/java/com/android/server/pm/UserSystemPackageInstaller.java
+++ b/services/core/java/com/android/server/pm/UserSystemPackageInstaller.java
@@ -449,7 +449,14 @@
     }
 
     void dump(PrintWriter pw) {
-        for (int i = 0; i < mWhitelitsedPackagesForUserTypes.size(); i++) {
+        pw.print("Whitelisted packages per user type");
+        final int size = mWhitelitsedPackagesForUserTypes.size();
+        if (size == 0) {
+            pw.println(": N/A");
+            return;
+        }
+        pw.println(" (" + size + " packages)");
+        for (int i = 0; i < size; i++) {
             final String pkgName = mWhitelitsedPackagesForUserTypes.keyAt(i);
             final String whitelistedUserTypes =
                     UserInfo.flagsToString(mWhitelitsedPackagesForUserTypes.valueAt(i));
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 5315634..89908f0 100644
--- a/services/core/java/com/android/server/pm/permission/PermissionManagerService.java
+++ b/services/core/java/com/android/server/pm/permission/PermissionManagerService.java
@@ -53,7 +53,6 @@
 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;
@@ -793,13 +792,13 @@
 
         final CheckPermissionDelegate checkPermissionDelegate;
         synchronized (mLock) {
-            if (mCheckPermissionDelegate == null)  {
-                return checkPermissionImpl(permName, pkgName, userId);
-            }
             checkPermissionDelegate = mCheckPermissionDelegate;
         }
+        if (checkPermissionDelegate == null) {
+            return checkPermissionImpl(permName, pkgName, userId);
+        }
         return checkPermissionDelegate.checkPermission(permName, pkgName, userId,
-                PermissionManagerService.this::checkPermissionImpl);
+                this::checkPermissionImpl);
     }
 
     private int checkPermissionImpl(String permName, String pkgName, int userId) {
@@ -845,23 +844,7 @@
 
     private boolean checkSinglePermissionInternal(int uid,
             @NonNull PermissionsState permissionsState, @NonNull String permissionName) {
-        boolean hasPermission = permissionsState.hasPermission(permissionName,
-                UserHandle.getUserId(uid));
-
-        if (!hasPermission && mSettings.isPermissionRuntime(permissionName)) {
-            final String[] packageNames = mContext.getPackageManager().getPackagesForUid(uid);
-            final int packageNamesSize = packageNames != null ? packageNames.length : 0;
-            for (int i = 0; i < packageNamesSize; i++) {
-                final PackageParser.Package pkg = mPackageManagerInt.getPackage(packageNames[i]);
-                if (pkg != null && pkg.applicationInfo.targetSdkVersion < Build.VERSION_CODES.M
-                        && pkg.requestedPermissions.contains(permissionName)) {
-                    hasPermission = true;
-                    break;
-                }
-            }
-        }
-
-        if (!hasPermission) {
+        if (!permissionsState.hasPermission(permissionName, UserHandle.getUserId(uid))) {
             return false;
         }
 
@@ -885,13 +868,13 @@
 
         final CheckPermissionDelegate checkPermissionDelegate;
         synchronized (mLock) {
-            if (mCheckPermissionDelegate == null)  {
-                return checkUidPermissionImpl(permName, uid);
-            }
             checkPermissionDelegate = mCheckPermissionDelegate;
         }
+        if (checkPermissionDelegate == null)  {
+            return checkUidPermissionImpl(permName, uid);
+        }
         return checkPermissionDelegate.checkUidPermission(permName, uid,
-                PermissionManagerService.this::checkUidPermissionImpl);
+                this::checkUidPermissionImpl);
     }
 
     private int checkUidPermissionImpl(String permName, int uid) {
@@ -1558,7 +1541,6 @@
             }
         };
 
-        final AppOpsManager appOpsManager = mContext.getSystemService(AppOpsManager.class);
         for (int i = 0; i < permissionCount; i++) {
             final String permName = pkg.requestedPermissions.get(i);
             final BasePermission bp;
@@ -1624,16 +1606,9 @@
 
             // 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) {
diff --git a/services/core/java/com/android/server/policy/PermissionPolicyService.java b/services/core/java/com/android/server/policy/PermissionPolicyService.java
index f3826e9e..df2b3ca 100644
--- a/services/core/java/com/android/server/policy/PermissionPolicyService.java
+++ b/services/core/java/com/android/server/policy/PermissionPolicyService.java
@@ -152,10 +152,10 @@
             for (int i = 0; i < numDangerousPerms; i++) {
                 PermissionInfo perm = dangerousPerms.get(i);
 
-                if (perm.isHardRestricted() || perm.backgroundPermission != null) {
+                if (perm.isRuntime()) {
                     appOpsService.startWatchingMode(getSwitchOp(perm.name), null, appOpsListener);
-                } else if (perm.isSoftRestricted()) {
-                    appOpsService.startWatchingMode(getSwitchOp(perm.name), null, appOpsListener);
+                }
+                if (perm.isSoftRestricted()) {
                     SoftRestrictedPermissionPolicy policy =
                             SoftRestrictedPermissionPolicy.forPermission(null, null, null,
                                     perm.name);
@@ -424,16 +424,6 @@
          */
         private final @NonNull ArrayList<OpToChange> mOpsToForeground = new ArrayList<>();
 
-        /**
-         * All ops that need to be flipped to foreground if allow.
-         *
-         * Currently, only used by the foreground/background permissions logic.
-         *
-         * @see #syncPackages
-         */
-        private final @NonNull ArrayList<OpToChange> mOpsToForegroundIfAllow =
-                new ArrayList<>();
-
         PermissionToOpSynchroniser(@NonNull Context context) {
             mContext = context;
             mPackageManager = context.getPackageManager();
@@ -443,7 +433,7 @@
         /**
          * Set app ops that were added in {@link #addPackage}.
          *
-         * <p>This processes ops previously added by {@link #addOpIfRestricted}
+         * <p>This processes ops previously added by {@link #addAppOps(PackageInfo, String)}
          */
         private void syncPackages() {
             // Remember which ops were already set. This makes sure that we always set the most
@@ -459,19 +449,6 @@
                 alreadySetAppOps.put(IntPair.of(op.uid, op.code), 1);
             }
 
-            final int foregroundIfAllowedCount = mOpsToForegroundIfAllow.size();
-            for (int i = 0; i < foregroundIfAllowedCount; i++) {
-                final OpToChange op = mOpsToForegroundIfAllow.get(i);
-                if (alreadySetAppOps.indexOfKey(IntPair.of(op.uid, op.code)) >= 0) {
-                    continue;
-                }
-
-                boolean wasSet = setUidModeForegroundIfAllow(op.code, op.uid, op.packageName);
-                if (wasSet) {
-                    alreadySetAppOps.put(IntPair.of(op.uid, op.code), 1);
-                }
-            }
-
             final int foregroundCount = mOpsToForeground.size();
             for (int i = 0; i < foregroundCount; i++) {
                 final OpToChange op = mOpsToForeground.get(i);
@@ -509,143 +486,139 @@
         }
 
         /**
-         * Add op that belong to a restricted permission for later processing in
-         * {@link #syncPackages()}.
-         *
-         * <p>Note: Called with the package lock held. Do <u>not</u> call into app-op manager.
-         *
-         * @param permissionInfo The permission that is currently looked at
-         * @param pkg The package looked at
+         * Note: Called with the package lock held. Do <u>not</u> call into app-op manager.
          */
-        private void addOpIfRestricted(@NonNull PermissionInfo permissionInfo,
-                @NonNull PackageInfo pkg) {
-            final String permission = permissionInfo.name;
-            final int opCode = getSwitchOp(permission);
-            final int uid = pkg.applicationInfo.uid;
-
-            if (!permissionInfo.isRestricted()) {
+        private void addAppOps(@NonNull PackageInfo packageInfo, @NonNull String permissionName) {
+            PermissionInfo permissionInfo = getPermissionInfo(permissionName);
+            if (permissionInfo == null) {
                 return;
             }
-
-            if (opCode != OP_NONE) {
-                int permissionFlags = mPackageManager.getPermissionFlags(permission,
-                        pkg.packageName, mContext.getUser());
-                boolean isReviewRequired = (permissionFlags & FLAG_PERMISSION_REVIEW_REQUIRED) != 0;
-                if (!isReviewRequired) {
-                    boolean isRevokedCompat =
-                            (permissionFlags & FLAG_PERMISSION_REVOKED_COMPAT) != 0;
-                    if (permissionInfo.isHardRestricted()) {
-                        boolean shouldApplyRestriction =
-                                (permissionFlags & FLAG_PERMISSION_APPLY_RESTRICTION) != 0;
-                        if (isRevokedCompat || shouldApplyRestriction) {
-                            mOpsToIgnore.add(new OpToChange(uid, pkg.packageName, opCode));
-                        } else {
-                            mOpsToAllow.add(new OpToChange(uid, pkg.packageName, opCode));
-                        }
-                    } else if (permissionInfo.isSoftRestricted()) {
-                        SoftRestrictedPermissionPolicy policy =
-                                SoftRestrictedPermissionPolicy.forPermission(mContext,
-                                        pkg.applicationInfo, mContext.getUser(), permission);
-                        if (!isRevokedCompat && policy.mayGrantPermission()) {
-                            mOpsToAllow.add(new OpToChange(uid, pkg.packageName, opCode));
-                        } else {
-                            mOpsToIgnore.add(new OpToChange(uid, pkg.packageName, opCode));
-                        }
-                    }
-                }
-            }
-
-            if (permissionInfo.isSoftRestricted()) {
-                SoftRestrictedPermissionPolicy policy =
-                        SoftRestrictedPermissionPolicy.forPermission(mContext, pkg.applicationInfo,
-                                mContext.getUser(), permission);
-                int extraOpCode = policy.getExtraAppOpCode();
-                if (extraOpCode != OP_NONE) {
-                    if (policy.mayAllowExtraAppOp()) {
-                        mOpsToAllow.add(new OpToChange(uid, pkg.packageName, extraOpCode));
-                    } else {
-                        if (policy.mayDenyExtraAppOpIfGranted()) {
-                            mOpsToIgnore.add(new OpToChange(uid, pkg.packageName, extraOpCode));
-                        } else {
-                            mOpsToIgnoreIfNotAllowed.add(new OpToChange(uid, pkg.packageName,
-                                    extraOpCode));
-                        }
-                    }
-                }
-            }
+            addPermissionAppOp(packageInfo, permissionInfo);
+            addExtraAppOp(packageInfo, permissionInfo);
         }
 
-        private boolean isBgPermRestricted(@NonNull String pkg, @NonNull String perm, int uid) {
-            try {
-                final PermissionInfo bgPermInfo = mPackageManager.getPermissionInfo(perm, 0);
-
-                if (bgPermInfo.isSoftRestricted()) {
-                    Slog.wtf(LOG_TAG, "Support for soft restricted background permissions not "
-                            + "implemented");
-                }
-
-                return bgPermInfo.isHardRestricted() && (mPackageManager.getPermissionFlags(
-                                perm, pkg, UserHandle.getUserHandleForUid(uid))
-                                & FLAG_PERMISSION_APPLY_RESTRICTION) != 0;
-            } catch (NameNotFoundException e) {
-                Slog.w(LOG_TAG, "Cannot read permission state of " + perm, e);
-                return false;
-            }
-        }
-
-        /**
-         * Add op that belong to a foreground permission for later processing in
-         * {@link #syncPackages()}.
-         *
-         * <p>Note: Called with the package lock held. Do <u>not</u> call into app-op manager.
-         *
-         * @param permissionInfo The permission that is currently looked at
-         * @param pkg The package looked at
-         */
-        private void addOpIfFgPermissions(@NonNull PermissionInfo permissionInfo,
-                @NonNull PackageInfo pkg) {
-            final String bgPermissionName = permissionInfo.backgroundPermission;
-
-            if (bgPermissionName == null) {
+        private void addPermissionAppOp(@NonNull PackageInfo packageInfo,
+                @NonNull PermissionInfo permissionInfo) {
+            if (!permissionInfo.isRuntime()) {
                 return;
             }
 
-            final String permission = permissionInfo.name;
-            final int opCode = getSwitchOp(permission);
-            final String pkgName = pkg.packageName;
-            final int uid = pkg.applicationInfo.uid;
-
-            // App does not support runtime permissions. Hence the state is encoded in the app-op.
-            // To not override unrecoverable state don't change app-op unless bg perm is reviewed.
-            if (pkg.applicationInfo.targetSdkVersion < Build.VERSION_CODES.M) {
-                // If the review is required for this permission, the grant state does not
-                // really matter. To have a stable state, don't change the app-op if review is still
-                // pending.
-                int flags = mPackageManager.getPermissionFlags(bgPermissionName,
-                        pkg.packageName, UserHandle.getUserHandleForUid(uid));
-
-                if ((flags & FLAG_PERMISSION_REVIEW_REQUIRED) == 0
-                        && isBgPermRestricted(pkgName, bgPermissionName, uid)) {
-                    mOpsToForegroundIfAllow.add(new OpToChange(uid, pkgName, opCode));
-                }
-
+            String permissionName = permissionInfo.name;
+            String packageName = packageInfo.packageName;
+            int permissionFlags = mPackageManager.getPermissionFlags(permissionName,
+                    packageName, mContext.getUser());
+            boolean isReviewRequired = (permissionFlags & FLAG_PERMISSION_REVIEW_REQUIRED) != 0;
+            if (isReviewRequired) {
                 return;
             }
 
-            if (mPackageManager.checkPermission(permission, pkgName)
-                    == PackageManager.PERMISSION_GRANTED) {
-                final boolean isBgHardRestricted = isBgPermRestricted(pkgName, bgPermissionName,
-                        uid);
-                final boolean isBgPermGranted = mPackageManager.checkPermission(bgPermissionName,
-                        pkgName) == PackageManager.PERMISSION_GRANTED;
+            // TODO: COARSE_LOCATION and FINE_LOCATION shares the same app op. We are solving this
+            //  with switch op but once we start syncing single permission this won't work.
+            int appOpCode = getSwitchOp(permissionName);
+            if (appOpCode == OP_NONE) {
+                // Note that background permissions don't have an associated app op.
+                return;
+            }
 
-                if (!isBgHardRestricted && isBgPermGranted) {
-                    mOpsToAllow.add(new OpToChange(uid, pkgName, opCode));
+            int appOpMode;
+            boolean shouldGrantAppOp = shouldGrantAppOp(packageInfo, permissionInfo);
+            if (shouldGrantAppOp) {
+                if (permissionInfo.backgroundPermission != null) {
+                    PermissionInfo backgroundPermissionInfo = getPermissionInfo(
+                            permissionInfo.backgroundPermission);
+                    boolean shouldGrantBackgroundAppOp = backgroundPermissionInfo != null
+                            && shouldGrantAppOp(packageInfo, backgroundPermissionInfo);
+                    appOpMode = shouldGrantBackgroundAppOp ? MODE_ALLOWED : MODE_FOREGROUND;
                 } else {
-                    mOpsToForeground.add(new OpToChange(uid, pkgName, opCode));
+                    appOpMode = MODE_ALLOWED;
                 }
             } else {
-                mOpsToIgnore.add(new OpToChange(uid, pkgName, opCode));
+                appOpMode = MODE_IGNORED;
+            }
+
+            int uid = packageInfo.applicationInfo.uid;
+            OpToChange opToChange = new OpToChange(uid, packageName, appOpCode);
+            switch (appOpMode) {
+                case MODE_ALLOWED:
+                    mOpsToAllow.add(opToChange);
+                    break;
+                case MODE_FOREGROUND:
+                    mOpsToForeground.add(opToChange);
+                    break;
+                case MODE_IGNORED:
+                    mOpsToIgnore.add(opToChange);
+                    break;
+            }
+        }
+
+        @Nullable
+        private PermissionInfo getPermissionInfo(@NonNull String permissionName) {
+            try {
+                return mPackageManager.getPermissionInfo(permissionName, 0);
+            } catch (PackageManager.NameNotFoundException e) {
+                return null;
+            }
+        }
+
+        private boolean shouldGrantAppOp(@NonNull PackageInfo packageInfo,
+                @NonNull PermissionInfo permissionInfo) {
+            String permissionName = permissionInfo.name;
+            String packageName = packageInfo.packageName;
+            boolean isGranted = mPackageManager.checkPermission(permissionName, packageName)
+                    == PackageManager.PERMISSION_GRANTED;
+            if (!isGranted) {
+                return false;
+            }
+
+            int permissionFlags = mPackageManager.getPermissionFlags(permissionName, packageName,
+                    mContext.getUser());
+            boolean isRevokedCompat = (permissionFlags & FLAG_PERMISSION_REVOKED_COMPAT)
+                    == FLAG_PERMISSION_REVOKED_COMPAT;
+            if (isRevokedCompat) {
+                return false;
+            }
+
+            if (permissionInfo.isHardRestricted()) {
+                boolean shouldApplyRestriction =
+                        (permissionFlags & FLAG_PERMISSION_APPLY_RESTRICTION)
+                                == FLAG_PERMISSION_APPLY_RESTRICTION;
+                return !shouldApplyRestriction;
+            } else if (permissionInfo.isSoftRestricted()) {
+                SoftRestrictedPermissionPolicy policy =
+                        SoftRestrictedPermissionPolicy.forPermission(mContext,
+                                packageInfo.applicationInfo, mContext.getUser(), permissionName);
+                return policy.mayGrantPermission();
+            } else {
+                return true;
+            }
+        }
+
+        private void addExtraAppOp(@NonNull PackageInfo packageInfo,
+                @NonNull PermissionInfo permissionInfo) {
+            if (!permissionInfo.isSoftRestricted()) {
+                return;
+            }
+
+            String permissionName = permissionInfo.name;
+            SoftRestrictedPermissionPolicy policy =
+                    SoftRestrictedPermissionPolicy.forPermission(mContext,
+                            packageInfo.applicationInfo, mContext.getUser(), permissionName);
+            int extraOpCode = policy.getExtraAppOpCode();
+            if (extraOpCode == OP_NONE) {
+                return;
+            }
+
+            int uid = packageInfo.applicationInfo.uid;
+            String packageName = packageInfo.packageName;
+            OpToChange extraOpToChange = new OpToChange(uid, packageName, extraOpCode);
+            if (policy.mayAllowExtraAppOp()) {
+                mOpsToAllow.add(extraOpToChange);
+            } else {
+                if (policy.mayDenyExtraAppOpIfGranted()) {
+                    mOpsToIgnore.add(extraOpToChange);
+                } else {
+                    mOpsToIgnoreIfNotAllowed.add(extraOpToChange);
+                }
             }
         }
 
@@ -671,20 +644,7 @@
             }
 
             for (String permission : pkg.requestedPermissions) {
-                final int opCode = getSwitchOp(permission);
-                if (opCode == OP_NONE) {
-                    continue;
-                }
-
-                final PermissionInfo permissionInfo;
-                try {
-                    permissionInfo = mPackageManager.getPermissionInfo(permission, 0);
-                } catch (PackageManager.NameNotFoundException e) {
-                    continue;
-                }
-
-                addOpIfRestricted(permissionInfo, pkg);
-                addOpIfFgPermissions(permissionInfo, pkg);
+                addAppOps(pkg, permission);
             }
         }
 
@@ -692,17 +652,6 @@
             setUidMode(opCode, uid, MODE_ALLOWED, packageName);
         }
 
-        private boolean setUidModeForegroundIfAllow(int opCode, int uid,
-                @NonNull String packageName) {
-            final int currentMode = mAppOpsManager.unsafeCheckOpRaw(AppOpsManager.opToPublicName(
-                    opCode), uid, packageName);
-            if (currentMode == MODE_ALLOWED) {
-                mAppOpsManager.setUidMode(opCode, uid, MODE_FOREGROUND);
-                return true;
-            }
-            return false;
-        }
-
         private void setUidModeForeground(int opCode, int uid, @NonNull String packageName) {
             setUidMode(opCode, uid, MODE_FOREGROUND, packageName);
         }
diff --git a/services/core/java/com/android/server/policy/PhoneWindowManager.java b/services/core/java/com/android/server/policy/PhoneWindowManager.java
index 88b1793..c851cc6 100644
--- a/services/core/java/com/android/server/policy/PhoneWindowManager.java
+++ b/services/core/java/com/android/server/policy/PhoneWindowManager.java
@@ -23,6 +23,7 @@
 import static android.app.WindowConfiguration.WINDOWING_MODE_SPLIT_SCREEN_PRIMARY;
 import static android.content.Context.CONTEXT_RESTRICTED;
 import static android.content.Context.WINDOW_SERVICE;
+import static android.content.pm.PackageManager.FEATURE_AUTOMOTIVE;
 import static android.content.pm.PackageManager.FEATURE_HDMI_CEC;
 import static android.content.pm.PackageManager.FEATURE_LEANBACK;
 import static android.content.pm.PackageManager.FEATURE_PICTURE_IN_PICTURE;
@@ -385,6 +386,7 @@
     BurnInProtectionHelper mBurnInProtectionHelper;
     private DisplayFoldController mDisplayFoldController;
     AppOpsManager mAppOpsManager;
+    private boolean mHasFeatureAuto;
     private boolean mHasFeatureWatch;
     private boolean mHasFeatureLeanback;
     private boolean mHasFeatureHdmiCec;
@@ -1753,6 +1755,7 @@
         mDisplayManager = mContext.getSystemService(DisplayManager.class);
         mHasFeatureWatch = mContext.getPackageManager().hasSystemFeature(FEATURE_WATCH);
         mHasFeatureLeanback = mContext.getPackageManager().hasSystemFeature(FEATURE_LEANBACK);
+        mHasFeatureAuto = mContext.getPackageManager().hasSystemFeature(FEATURE_AUTOMOTIVE);
         mHasFeatureHdmiCec = mContext.getPackageManager().hasSystemFeature(FEATURE_HDMI_CEC);
         mAccessibilityShortcutController =
                 new AccessibilityShortcutController(mContext, new Handler(), mCurrentUserId);
@@ -4540,6 +4543,12 @@
     private void wakeUpFromPowerKey(long eventTime) {
         wakeUp(eventTime, mAllowTheaterModeWakeFromPowerKey,
                 PowerManager.WAKE_REASON_POWER_BUTTON, "android.policy:POWER");
+
+        // Turn on the connected TV and switch HDMI input if we're a HDMI playback device.
+        final HdmiControl hdmiControl = getHdmiControl();
+        if (hdmiControl != null) {
+            hdmiControl.turnOnTv();
+        }
     }
 
     private boolean wakeUp(long wakeTime, boolean wakeInTheaterMode, @WakeReason int reason,
@@ -4572,7 +4581,7 @@
         // ... eventually calls finishWindowsDrawn which will finalize our screen turn on
         // as well as enabling the orientation change logic/sensor.
         mWindowManagerInternal.waitForAllWindowsDrawn(mWindowManagerDrawCallback,
-                WAITING_FOR_DRAWN_TIMEOUT);
+                WAITING_FOR_DRAWN_TIMEOUT, INVALID_DISPLAY);
     }
 
     // Called on the DisplayManager's DisplayPowerController thread.
@@ -5222,7 +5231,7 @@
             awakenDreams();
         }
 
-        if (!isUserSetupComplete()) {
+        if (!mHasFeatureAuto && !isUserSetupComplete()) {
             Slog.i(TAG, "Not going home because user setup is in progress.");
             return;
         }
diff --git a/services/core/java/com/android/server/role/RoleManagerService.java b/services/core/java/com/android/server/role/RoleManagerService.java
index 282fed8..aac0f90 100644
--- a/services/core/java/com/android/server/role/RoleManagerService.java
+++ b/services/core/java/com/android/server/role/RoleManagerService.java
@@ -51,7 +51,6 @@
 import android.os.UserHandle;
 import android.os.UserManagerInternal;
 import android.service.sms.FinancialSmsService;
-import android.telephony.IFinancialSmsCallback;
 import android.text.TextUtils;
 import android.util.ArrayMap;
 import android.util.ArraySet;
@@ -702,40 +701,6 @@
             dumpOutputStream.flush();
         }
 
-        /**
-         * Get filtered SMS messages for financial app.
-         */
-        @Override
-        public void getSmsMessagesForFinancialApp(
-                String callingPkg, Bundle params, IFinancialSmsCallback callback) {
-            int mode = PermissionChecker.checkCallingOrSelfPermission(
-                    getContext(),
-                    AppOpsManager.OPSTR_SMS_FINANCIAL_TRANSACTIONS);
-
-            if (mode == PermissionChecker.PERMISSION_GRANTED) {
-                FinancialSmsManager financialSmsManager = new FinancialSmsManager(getContext());
-                financialSmsManager.getSmsMessages(new RemoteCallback((result) -> {
-                    CursorWindow messages = null;
-                    if (result == null) {
-                        Slog.w(LOG_TAG, "result is null.");
-                    } else {
-                        messages = result.getParcelable(FinancialSmsService.EXTRA_SMS_MSGS);
-                    }
-                    try {
-                        callback.onGetSmsMessagesForFinancialApp(messages);
-                    } catch (RemoteException e) {
-                        // do nothing
-                    }
-                }), params);
-            } else {
-                try {
-                    callback.onGetSmsMessagesForFinancialApp(null);
-                } catch (RemoteException e) {
-                    // do nothing
-                }
-            }
-        }
-
         private int getUidForPackage(String packageName) {
             long ident = Binder.clearCallingIdentity();
             try {
diff --git a/services/core/java/com/android/server/rollback/RollbackPackageHealthObserver.java b/services/core/java/com/android/server/rollback/RollbackPackageHealthObserver.java
index 9c19aec..83891f6 100644
--- a/services/core/java/com/android/server/rollback/RollbackPackageHealthObserver.java
+++ b/services/core/java/com/android/server/rollback/RollbackPackageHealthObserver.java
@@ -370,7 +370,7 @@
     private void checkAndMitigateNativeCrashes() {
         mNumberOfNativeCrashPollsRemaining--;
         // Check if native watchdog reported a crash
-        if ("1".equals(SystemProperties.get("ro.init.updatable_crashing"))) {
+        if ("1".equals(SystemProperties.get("sys.init.updatable_crashing"))) {
             execute(getModuleMetadataPackage());
             // we stop polling after an attempt to execute rollback, regardless of whether the
             // attempt succeeds or not
diff --git a/services/core/java/com/android/server/rollback/RollbackStore.java b/services/core/java/com/android/server/rollback/RollbackStore.java
index eadd09c..425da37 100644
--- a/services/core/java/com/android/server/rollback/RollbackStore.java
+++ b/services/core/java/com/android/server/rollback/RollbackStore.java
@@ -28,6 +28,7 @@
 import android.util.SparseLongArray;
 
 import com.android.internal.annotations.GuardedBy;
+import com.android.internal.annotations.VisibleForTesting;
 
 import libcore.io.IoUtils;
 
@@ -288,19 +289,25 @@
             JSONObject dataJson = new JSONObject(
                     IoUtils.readFileAsString(rollbackJsonFile.getAbsolutePath()));
 
-            return new Rollback(
-                    rollbackInfoFromJson(dataJson.getJSONObject("info")),
-                    backupDir,
-                    Instant.parse(dataJson.getString("timestamp")),
-                    dataJson.getInt("stagedSessionId"),
-                    rollbackStateFromString(dataJson.getString("state")),
-                    dataJson.getInt("apkSessionId"),
-                    dataJson.getBoolean("restoreUserDataInProgress"));
+            return rollbackFromJson(dataJson, backupDir);
         } catch (JSONException | DateTimeParseException | ParseException e) {
             throw new IOException(e);
         }
     }
 
+    @VisibleForTesting
+    static Rollback rollbackFromJson(JSONObject dataJson, File backupDir)
+            throws JSONException, ParseException {
+        return new Rollback(
+                rollbackInfoFromJson(dataJson.getJSONObject("info")),
+                backupDir,
+                Instant.parse(dataJson.getString("timestamp")),
+                dataJson.getInt("stagedSessionId"),
+                rollbackStateFromString(dataJson.getString("state")),
+                dataJson.getInt("apkSessionId"),
+                dataJson.getBoolean("restoreUserDataInProgress"));
+    }
+
     private static JSONObject toJson(VersionedPackage pkg) throws JSONException {
         JSONObject json = new JSONObject();
         json.put("packageName", pkg.getPackageName());
diff --git a/services/core/java/com/android/server/slice/SliceManagerService.java b/services/core/java/com/android/server/slice/SliceManagerService.java
index 5fd2ab8..3b2f324 100644
--- a/services/core/java/com/android/server/slice/SliceManagerService.java
+++ b/services/core/java/com/android/server/slice/SliceManagerService.java
@@ -180,8 +180,13 @@
         verifyCaller(pkg);
         enforceAccess(pkg, uri);
         uri = maybeAddUserId(uri, Binder.getCallingUserHandle().getIdentifier());
-        if (getPinnedSlice(uri).unpin(pkg, token)) {
-            removePinnedSlice(uri);
+        try {
+            PinnedSliceState slice = getPinnedSlice(uri);
+            if (slice != null && slice.unpin(pkg, token)) {
+                removePinnedSlice(uri);
+            }
+        } catch (IllegalStateException exception) {
+            Slog.w(TAG, exception.getMessage());
         }
     }
 
diff --git a/services/core/java/com/android/server/statusbar/StatusBarManagerService.java b/services/core/java/com/android/server/statusbar/StatusBarManagerService.java
index 8897eca..3439d38 100644
--- a/services/core/java/com/android/server/statusbar/StatusBarManagerService.java
+++ b/services/core/java/com/android/server/statusbar/StatusBarManagerService.java
@@ -609,13 +609,13 @@
     }
 
     @Override
-    public void showBiometricDialog(Bundle bundle, IBiometricServiceReceiverInternal receiver,
-            int type, boolean requireConfirmation, int userId, String opPackageName) {
+    public void showAuthenticationDialog(Bundle bundle, IBiometricServiceReceiverInternal receiver,
+            int biometricModality, boolean requireConfirmation, int userId, String opPackageName) {
         enforceBiometricDialog();
         if (mBar != null) {
             try {
-                mBar.showBiometricDialog(bundle, receiver, type, requireConfirmation, userId,
-                        opPackageName);
+                mBar.showAuthenticationDialog(bundle, receiver, biometricModality,
+                        requireConfirmation, userId, opPackageName);
             } catch (RemoteException ex) {
             }
         }
@@ -644,22 +644,22 @@
     }
 
     @Override
-    public void onBiometricError(String error) {
+    public void onBiometricError(int errorCode, String error) {
         enforceBiometricDialog();
         if (mBar != null) {
             try {
-                mBar.onBiometricError(error);
+                mBar.onBiometricError(errorCode, error);
             } catch (RemoteException ex) {
             }
         }
     }
 
     @Override
-    public void hideBiometricDialog() {
+    public void hideAuthenticationDialog() {
         enforceBiometricDialog();
         if (mBar != null) {
             try {
-                mBar.hideBiometricDialog();
+                mBar.hideAuthenticationDialog();
             } catch (RemoteException ex) {
             }
         }
diff --git a/services/core/java/com/android/server/textclassifier/TextClassificationManagerService.java b/services/core/java/com/android/server/textclassifier/TextClassificationManagerService.java
index 4c93564..5493afd 100644
--- a/services/core/java/com/android/server/textclassifier/TextClassificationManagerService.java
+++ b/services/core/java/com/android/server/textclassifier/TextClassificationManagerService.java
@@ -365,10 +365,16 @@
     protected void dump(FileDescriptor fd, PrintWriter fout, String[] args) {
         if (!DumpUtils.checkDumpPermission(mContext, LOG_TAG, fout)) return;
         IndentingPrintWriter pw = new IndentingPrintWriter(fout, "  ");
-        TextClassificationManager tcm = mContext.getSystemService(TextClassificationManager.class);
-        tcm.dump(pw);
 
-        pw.printPair("context", mContext); pw.println();
+        // Create a TCM instance with the system server identity. TCM creates a ContentObserver
+        // to listen for settings changes. It does not pass the checkContentProviderAccess check
+        // if we are using the shell identity, because AMS does not track of processes spawn from
+        // shell.
+        Binder.withCleanCallingIdentity(
+                () -> mContext.getSystemService(TextClassificationManager.class).dump(pw));
+
+        pw.printPair("context", mContext);
+        pw.println();
         synchronized (mLock) {
             int size = mUserStates.size();
             pw.print("Number user states: "); pw.println(size);
diff --git a/services/core/java/com/android/server/wm/AccessibilityController.java b/services/core/java/com/android/server/wm/AccessibilityController.java
index 59f051b..10415f5 100644
--- a/services/core/java/com/android/server/wm/AccessibilityController.java
+++ b/services/core/java/com/android/server/wm/AccessibilityController.java
@@ -271,11 +271,11 @@
         }
     }
 
-    /** NOTE: This has to be called within a surface transaction. */
-    public void drawMagnifiedRegionBorderIfNeededLocked(int displayId) {
+    public void drawMagnifiedRegionBorderIfNeededLocked(int displayId,
+            SurfaceControl.Transaction t) {
         final DisplayMagnifier displayMagnifier = mDisplayMagnifiers.get(displayId);
         if (displayMagnifier != null) {
-            displayMagnifier.drawMagnifiedRegionBorderIfNeededLocked();
+            displayMagnifier.drawMagnifiedRegionBorderIfNeededLocked(t);
         }
         // Not relevant for the window observer.
     }
@@ -431,7 +431,7 @@
                 Slog.i(LOG_TAG, "Rotation: " + Surface.rotationToString(rotation)
                         + " displayId: " + displayContent.getDisplayId());
             }
-            mMagnifedViewport.onRotationChangedLocked();
+            mMagnifedViewport.onRotationChangedLocked(displayContent.getPendingTransaction());
             mHandler.sendEmptyMessage(MyHandler.MESSAGE_NOTIFY_ROTATION_CHANGED);
         }
 
@@ -536,9 +536,8 @@
                     .sendToTarget();
         }
 
-        /** NOTE: This has to be called within a surface transaction. */
-        public void drawMagnifiedRegionBorderIfNeededLocked() {
-            mMagnifedViewport.drawWindowIfNeededLocked();
+        public void drawMagnifiedRegionBorderIfNeededLocked(SurfaceControl.Transaction t) {
+            mMagnifedViewport.drawWindowIfNeededLocked(t);
         }
 
         private final class MagnifiedViewport {
@@ -744,7 +743,7 @@
                 return letterboxBounds;
             }
 
-            public void onRotationChangedLocked() {
+            public void onRotationChangedLocked(SurfaceControl.Transaction t) {
                 // If we are showing the magnification border, hide it immediately so
                 // the user does not see strange artifacts during rotation. The screenshot
                 // used for rotation already has the border. After the rotation is complete
@@ -758,7 +757,7 @@
                     mHandler.sendMessageDelayed(message, delay);
                 }
                 recomputeBoundsLocked();
-                mWindow.updateSize();
+                mWindow.updateSize(t);
             }
 
             public void setMagnifiedRegionBorderShownLocked(boolean shown, boolean animate) {
@@ -784,10 +783,9 @@
                 return mMagnificationSpec;
             }
 
-            /** NOTE: This has to be called within a surface transaction. */
-            public void drawWindowIfNeededLocked() {
+            public void drawWindowIfNeededLocked(SurfaceControl.Transaction t) {
                 recomputeBoundsLocked();
-                mWindow.drawIfNeeded();
+                mWindow.drawIfNeeded(t);
             }
 
             public void destroyWindow() {
@@ -837,10 +835,11 @@
                         /* ignore */
                     }
                     mSurfaceControl = surfaceControl;
-                    mSurfaceControl.setLayer(mService.mPolicy.getWindowLayerFromTypeLw(
-                            TYPE_MAGNIFICATION_OVERLAY)
-                            * WindowManagerService.TYPE_LAYER_MULTIPLIER);
-                    mSurfaceControl.setPosition(0, 0);
+                    mService.mTransactionFactory.get().setLayer(mSurfaceControl,
+                            mService.mPolicy.getWindowLayerFromTypeLw(TYPE_MAGNIFICATION_OVERLAY)
+                                    * WindowManagerService.TYPE_LAYER_MULTIPLIER)
+                            .setPosition(mSurfaceControl, 0, 0)
+                            .apply();
                     mSurface.copyFrom(mSurfaceControl);
 
                     mAnimationController = new AnimationController(context,
@@ -905,10 +904,10 @@
                     }
                 }
 
-                public void updateSize() {
+                public void updateSize(SurfaceControl.Transaction t) {
                     synchronized (mService.mGlobalLock) {
                         mWindowManager.getDefaultDisplay().getRealSize(mTempPoint);
-                        mSurfaceControl.setBufferSize(mTempPoint.x, mTempPoint.y);
+                        t.setBufferSize(mSurfaceControl, mTempPoint.x, mTempPoint.y);
                         invalidate(mDirtyRect);
                     }
                 }
@@ -923,8 +922,7 @@
                     mService.scheduleAnimationLocked();
                 }
 
-                /** NOTE: This has to be called within a surface transaction. */
-                public void drawIfNeeded() {
+                public void drawIfNeeded(SurfaceControl.Transaction t) {
                     synchronized (mService.mGlobalLock) {
                         if (!mInvalidated) {
                             return;
@@ -959,9 +957,9 @@
                             canvas.drawPath(path, mPaint);
 
                             mSurface.unlockCanvasAndPost(canvas);
-                            mSurfaceControl.show();
+                            t.show(mSurfaceControl);
                         } else {
-                            mSurfaceControl.hide();
+                            t.hide(mSurfaceControl);
                         }
                     }
                 }
diff --git a/services/core/java/com/android/server/wm/ActivityRecord.java b/services/core/java/com/android/server/wm/ActivityRecord.java
index c9e84ec..4f52d9d 100644
--- a/services/core/java/com/android/server/wm/ActivityRecord.java
+++ b/services/core/java/com/android/server/wm/ActivityRecord.java
@@ -54,20 +54,14 @@
 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_SHOW_WHEN_LOCKED;
 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;
@@ -86,7 +80,6 @@
 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.view.Display.DEFAULT_DISPLAY;
@@ -96,7 +89,7 @@
 import static android.view.WindowManager.TRANSIT_ACTIVITY_CLOSE;
 import static android.view.WindowManager.TRANSIT_TASK_CLOSE;
 
-import static com.android.server.am.ActivityRecordProto.CONFIGURATION_CONTAINER;
+import static com.android.server.am.ActivityRecordProto.APP_WINDOW_TOKEN;
 import static com.android.server.am.ActivityRecordProto.FRONT_OF_TASK;
 import static com.android.server.am.ActivityRecordProto.IDENTIFIER;
 import static com.android.server.am.ActivityRecordProto.PROC_ID;
@@ -151,12 +144,10 @@
 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.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_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.TAG_WM;
@@ -211,7 +202,6 @@
 import android.os.Process;
 import android.os.RemoteException;
 import android.os.SystemClock;
-import android.os.UserHandle;
 import android.os.storage.StorageManager;
 import android.service.voice.IVoiceInteractionSession;
 import android.util.ArraySet;
@@ -225,16 +215,12 @@
 import android.view.DisplayCutout;
 import android.view.IAppTransitionAnimationSpecsFuture;
 import android.view.IApplicationToken;
-import android.view.RemoteAnimationDefinition;
 import android.view.WindowManager.LayoutParams;
 
-import com.android.internal.R;
 import com.android.internal.annotations.VisibleForTesting;
 import com.android.internal.app.ResolverActivity;
 import com.android.internal.content.ReferrerIntent;
 import com.android.internal.util.XmlUtils;
-import com.android.server.AttributeCache;
-import com.android.server.AttributeCache.Entry;
 import com.android.server.am.AppTimeTracker;
 import com.android.server.am.EventLogTags;
 import com.android.server.am.PendingIntentRecord;
@@ -262,7 +248,7 @@
 /**
  * An entry in the history stack, representing an activity.
  */
-final class ActivityRecord extends ConfigurationContainer {
+final class ActivityRecord extends AppWindowToken {
     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;
@@ -291,29 +277,17 @@
     // How many activities have to be scheduled to stop to force a stop pass.
     private static final int MAX_STOPPING_TO_FORCE = 3;
 
-    final ActivityTaskManagerService mAtmService; // owner
-    final IApplicationToken.Stub appToken; // window manager token
-    // TODO: Remove after unification
-    AppWindowToken mAppWindowToken;
-
+    // TODO: Move to AppWindowToken?
     final ActivityInfo info; // activity info provided by developer in AndroidManifest
     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.
-    final int mUserId;          // Which user is this running for?
     final Intent intent;    // the original intent that generated us
-    final ComponentName mActivityComponent;  // the intent component, or target of an alias.
     final String shortComponentName; // the short component name of the intent
     final String resolvedType; // as per original caller;
-    final String packageName; // the package implementing intent's component
     final String processName; // process where this component wants to run
     final String taskAffinity; // as per ActivityInfo.taskAffinity
     final boolean stateNotNeeded; // As per ActivityInfo.flags
-    boolean fullscreen; // The activity is opaque and fills the entire space of this task.
-    // TODO: See if it possible to combine this with the fullscreen field.
-    final boolean hasWallpaper; // Has a wallpaper window as a background.
-    @VisibleForTesting
-    boolean noDisplay;  // activity is not displayed?
     @VisibleForTesting
     int mHandoverLaunchDisplayId = INVALID_DISPLAY; // Handover launch display id to next activity.
     private final boolean componentSpecified;  // did caller specify an explicit component?
@@ -324,7 +298,6 @@
     private int icon;               // resource identifier of activity's icon.
     private int logo;               // resource identifier of activity's logo.
     private int theme;              // resource identifier of activity's theme.
-    private int realTheme;          // actual theme resource we will use, never 0.
     private int windowFlags;        // custom window flags for preview window.
     private TaskRecord task;        // the task this is in.
     private long createTime = System.currentTimeMillis();
@@ -374,6 +347,7 @@
     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.
     private boolean mDeferHidingClient; // If true we told WM to defer reporting to the client
                                         // process that it is hidden.
     boolean sleeping;       // have we told the activity to sleep?
@@ -393,8 +367,6 @@
     long lastLaunchTime;    // time of last launch of this activity
     ComponentName requestedVrComponent; // the requested component for handling VR mode.
 
-    String stringName;      // for caching of toString().
-
     private boolean inHistory;  // are we in the history stack?
     final ActivityStackSupervisor mStackSupervisor;
     final RootActivityContainer mRootActivityContainer;
@@ -411,8 +383,6 @@
     int mRelaunchReason = RELAUNCH_REASON_NONE;
 
     TaskDescription taskDescription; // the recents information for this activity
-    boolean mLaunchTaskBehind; // this activity is actively being launched with
-        // ActivityOptions.setLaunchTaskBehind, will be cleared once launch is completed.
 
     // These configurations are collected from application's resources based on size-sensitive
     // qualifiers. For example, layout-w800dp will be added to mHorizontalSizeConfigurations as 800
@@ -430,17 +400,6 @@
     boolean pendingVoiceInteractionStart;   // Waiting for activity-invoked voice session
     IVoiceInteractionSession voiceSession;  // Voice interaction session for this activity
 
-    // 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 boolean mShowWhenLocked;
-    private boolean mInheritShownWhenLocked;
-    private boolean mTurnScreenOn;
-
     /**
      * Current sequencing integer of the configuration, for skipping old activity configurations.
      */
@@ -603,7 +562,7 @@
                 pw.print(" idle="); pw.print(idle);
                 pw.print(" mStartingWindowState=");
                 pw.println(startingWindowStateToString(mStartingWindowState));
-        pw.print(prefix); pw.print("fullscreen="); pw.print(fullscreen);
+        pw.print(prefix); pw.print("occludesParent="); pw.print(occludesParent());
                 pw.print(" noDisplay="); pw.print(noDisplay);
                 pw.print(" immersive="); pw.print(immersive);
                 pw.print(" launchMode="); pw.println(launchMode);
@@ -855,22 +814,7 @@
         }
     }
 
-    @Override
-    protected int getChildCount() {
-        // {@link ActivityRecord} is a leaf node and has no children.
-        return 0;
-    }
-
-    @Override
-    protected ConfigurationContainer getChildAt(int index) {
-        return null;
-    }
-
-    @Override
-    protected ConfigurationContainer getParent() {
-        return getTaskRecord();
-    }
-
+    // TODO: Remove once TaskRecord and Task are unified.
     TaskRecord getTaskRecord() {
         return task;
     }
@@ -914,31 +858,63 @@
 
         this.task = task;
 
-        if (!reparenting) {
+        // This is attaching the activity to the task which we only want to do once.
+        // TODO: Need to re-work after unifying the task level since it will already have a parent
+        // then. Just need to restructure the re-parent case not to do this. NOTE that the
+        // reparenting flag passed in can't be used directly for this as it isn't set in
+        // ActivityRecord#reparent() case that ends up calling this method.
+        if (task != null && getParent() == null) {
+            inHistory = true;
+            final Task container = task.getTask();
+            if (container != null) {
+                onAttachToTask(task.voiceSession != null, container.getDisplayContent(),
+                        getInputDispatchingTimeoutLocked(this) * 1000000L);
+                ProtoLog.v(WM_DEBUG_ADD_REMOVE, "setTask: %s at top.", this);
+                container.addChild(this, Integer.MAX_VALUE /* add on top */);
+            }
+
+            // TODO(b/36505427): Maybe this call should be moved inside
+            // updateOverrideConfiguration()
+            task.updateOverrideConfigurationFromLaunchBounds();
+            // Make sure override configuration is up-to-date before using to create window
+            // controller.
+            updateOverrideConfiguration();
+
+            task.addActivityToTop(this);
+
+            // When an activity is started directly into a split-screen fullscreen stack, we need to
+            // update the initial multi-window modes so that the callbacks are scheduled correctly
+            // when the user leaves that mode.
+            mLastReportedMultiWindowMode = inMultiWindowMode();
+            mLastReportedPictureInPictureMode = inPinnedWindowingMode();
+        } else if (!reparenting) {
             onParentChanged();
         }
     }
 
     /**
-     * Notifies AWT that this app is waiting to pause in order to determine if it will enter PIP.
-     * This information helps AWT know that the app is in the process of pausing before it gets the
-     * signal on the WM side.
+     * Sets the Task on this activity for the purposes of re-use during launch where we will
+     * re-use another activity instead of this one for the launch.
      */
-    void setWillCloseOrEnterPip(boolean willCloseOrEnterPip) {
-        if (mAppWindowToken == null) {
-            return;
-        }
-
-        mAppWindowToken.setWillCloseOrEnterPip(willCloseOrEnterPip);
+    void setTaskForReuse(TaskRecord task) {
+        this.task = task;
     }
 
     static class Token extends IApplicationToken.Stub {
-        private final WeakReference<ActivityRecord> weakActivity;
+        private WeakReference<ActivityRecord> weakActivity;
         private final String name;
+        private final String tokenString;
 
-        Token(ActivityRecord activity, Intent intent) {
-            weakActivity = new WeakReference<>(activity);
+        Token(Intent intent) {
             name = intent.getComponent().flattenToShortString();
+            tokenString = "Token{" + Integer.toHexString(System.identityHashCode(this)) + "}";
+        }
+
+        private void attach(ActivityRecord activity) {
+            if (weakActivity != null) {
+                throw new IllegalStateException("Already attached..." + this);
+            }
+            weakActivity = new WeakReference<>(activity);
         }
 
         private static @Nullable ActivityRecord tokenToActivityRecordLocked(Token token) {
@@ -958,7 +934,9 @@
             sb.append("Token{");
             sb.append(Integer.toHexString(System.identityHashCode(this)));
             sb.append(' ');
-            sb.append(weakActivity.get());
+            if (weakActivity != null) {
+                sb.append(weakActivity.get());
+            }
             sb.append('}');
             return sb.toString();
         }
@@ -1005,14 +983,15 @@
             ActivityRecord _resultTo, String _resultWho, int _reqCode, boolean _componentSpecified,
             boolean _rootVoiceInteraction, ActivityStackSupervisor supervisor,
             ActivityOptions options, ActivityRecord sourceRecord) {
-        mAtmService = _service;
+        super(_service.mWindowManager, _service, new Token(_intent), aInfo, options, _intent,
+                null /* displayContent */);
+        appToken.attach(this);
+
         mRootActivityContainer = _service.mRootActivityContainer;
-        appToken = new Token(this, _intent);
         info = aInfo;
         launchedFromPid = _launchedFromPid;
         launchedFromUid = _launchedFromUid;
         launchedFromPackage = _launchedFromPackage;
-        mUserId = UserHandle.getUserId(aInfo.applicationInfo.uid);
         intent = _intent;
         shortComponentName = _intent.getComponent().flattenToShortString();
         resolvedType = _resolvedType;
@@ -1037,17 +1016,6 @@
         hasBeenLaunched = false;
         mStackSupervisor = supervisor;
 
-        // 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 (aInfo.targetActivity == null
-                || (aInfo.targetActivity.equals(_intent.getComponent().getClassName())
-                && (aInfo.launchMode == LAUNCH_MULTIPLE
-                || aInfo.launchMode == LAUNCH_SINGLE_TOP))) {
-            mActivityComponent = _intent.getComponent();
-        } else {
-            mActivityComponent = new ComponentName(aInfo.packageName, aInfo.targetActivity);
-        }
         taskAffinity = aInfo.taskAffinity;
         stateNotNeeded = (aInfo.flags & FLAG_STATE_NOT_NEEDED) != 0;
         nonLocalizedLabel = aInfo.nonLocalizedLabel;
@@ -1060,11 +1028,6 @@
         icon = aInfo.getIconResource();
         logo = aInfo.getLogoResource();
         theme = aInfo.getThemeResource();
-        realTheme = theme;
-        if (realTheme == 0) {
-            realTheme = aInfo.applicationInfo.targetSdkVersion < HONEYCOMB
-                    ? android.R.style.Theme : android.R.style.Theme_Holo;
-        }
         if ((aInfo.flags & ActivityInfo.FLAG_HARDWARE_ACCELERATED) != 0) {
             windowFlags |= LayoutParams.FLAG_HARDWARE_ACCELERATED;
         }
@@ -1080,21 +1043,8 @@
             intent.addFlags(FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS);
         }
 
-        packageName = aInfo.applicationInfo.packageName;
         launchMode = aInfo.launchMode;
 
-        Entry ent = AttributeCache.instance().get(packageName,
-                realTheme, com.android.internal.R.styleable.Window, mUserId);
-
-        if (ent != null) {
-            fullscreen = !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;
-        }
-
         setActivityType(_componentSpecified, _launchedFromUid, _intent, options, sourceRecord);
 
         immersive = (aInfo.flags & FLAG_IMMERSIVE) != 0;
@@ -1102,11 +1052,6 @@
         requestedVrComponent = (aInfo.requestedVrComponent == null) ?
                 null : ComponentName.unflattenFromString(aInfo.requestedVrComponent);
 
-        mShowWhenLocked = (aInfo.flags & FLAG_SHOW_WHEN_LOCKED) != 0;
-        mInheritShownWhenLocked = (aInfo.privateFlags & FLAG_INHERIT_SHOW_WHEN_LOCKED) != 0;
-        mTurnScreenOn = (aInfo.flags & FLAG_TURN_SCREEN_ON) != 0;
-
-        mRotationAnimationHint = aInfo.rotationAnimation;
         lockTaskLaunchMode = aInfo.lockTaskLaunchMode;
         if (info.applicationInfo.isPrivilegedApp()
                 && (lockTaskLaunchMode == LOCK_TASK_LAUNCH_MODE_ALWAYS
@@ -1116,13 +1061,6 @@
 
         if (options != null) {
             pendingOptions = options;
-            mLaunchTaskBehind = options.getLaunchTaskBehind();
-
-            final int rotationAnimation = pendingOptions.getRotationAnimationHint();
-            // Only override manifest supplied option if set.
-            if (rotationAnimation >= 0) {
-                mRotationAnimationHint = rotationAnimation;
-            }
             final PendingIntent usageReport = pendingOptions.getUsageTimeReport();
             if (usageReport != null) {
                 appTimeTracker = new AppTimeTracker(usageReport);
@@ -1152,53 +1090,6 @@
         return hasProcess() && app.hasThread();
     }
 
-    void createAppWindowToken() {
-        if (mAppWindowToken != null) {
-            throw new IllegalArgumentException("App Window Token=" + mAppWindowToken
-                    + " already created for r=" + this);
-        }
-
-        inHistory = true;
-
-        // TODO(b/36505427): Maybe this call should be moved inside updateOverrideConfiguration()
-        task.updateOverrideConfigurationFromLaunchBounds();
-        // Make sure override configuration is up-to-date before using to create window controller.
-        updateOverrideConfiguration();
-
-        // TODO: remove after unification
-        mAppWindowToken = mAtmService.mWindowManager.mRoot.getAppWindowToken(appToken.asBinder());
-        if (mAppWindowToken != null) {
-            // TODO: Should this throw an exception instead?
-            Slog.w(TAG, "Attempted to add existing app token: " + appToken);
-        } else {
-            final Task container = task.getTask();
-            if (container == null) {
-                throw new IllegalArgumentException("createAppWindowToken: invalid task =" + task);
-            }
-            mAppWindowToken = createAppWindow(mAtmService.mWindowManager, appToken,
-                    task.voiceSession != null, container.getDisplayContent(),
-                    ActivityTaskManagerService.getInputDispatchingTimeoutLocked(this)
-                            * 1000000L, fullscreen,
-                    (info.flags & FLAG_SHOW_FOR_ALL_USERS) != 0,
-                    info.applicationInfo.targetSdkVersion,
-                    info.screenOrientation, mRotationAnimationHint,
-                    mLaunchTaskBehind, isAlwaysFocusable());
-            ProtoLog.v(WM_DEBUG_ADD_REMOVE, "addAppToken: %s"
-                            + " task=%s at %d", mAppWindowToken, container,
-                    Integer.MAX_VALUE);
-
-            container.addChild(mAppWindowToken, Integer.MAX_VALUE /* add on top */);
-        }
-
-        task.addActivityToTop(this);
-
-        // When an activity is started directly into a split-screen fullscreen stack, we need to
-        // update the initial multi-window modes so that the callbacks are scheduled correctly when
-        // the user leaves that mode.
-        mLastReportedMultiWindowMode = inMultiWindowMode();
-        mLastReportedPictureInPictureMode = inPinnedWindowingMode();
-    }
-
     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,
@@ -1207,40 +1098,20 @@
                     + " pkg=%s transferFrom=%s newTask=%b taskSwitch=%b processRunning=%b"
                     + " allowTaskSnapshot=%b", appToken, pkg, transferFrom, newTask, taskSwitch,
                 processRunning, allowTaskSnapshot);
-
-        if (mAppWindowToken == null) {
-            Slog.w(TAG_WM, "Attempted to set icon of non-existing app token: " + appToken);
-            return false;
-        }
-        if (mAppWindowToken.getTask() == null) {
-            // Can be removed after unification of Task and TaskRecord.
+        if (getParent() == null) {
             Slog.w(TAG_WM, "Attempted to start a window to an app token not having attached to any"
                     + " task: " + appToken);
             return false;
         }
-        return mAppWindowToken.addStartingWindow(pkg, theme, compatInfo, nonLocalizedLabel,
+        return super.addStartingWindow(pkg, theme, compatInfo, nonLocalizedLabel,
                 labelRes, icon, logo, windowFlags, transferFrom, newTask, taskSwitch,
                 processRunning, allowTaskSnapshot, activityCreated, fromRecents);
     }
 
-    // TODO: Remove after unification
-    @VisibleForTesting
-    AppWindowToken createAppWindow(WindowManagerService service, IApplicationToken token,
-            boolean voiceInteraction, DisplayContent dc, long inputDispatchingTimeoutNanos,
-            boolean fullscreen, boolean showForAllUsers, int targetSdk, int orientation,
-            int rotationAnimationHint, boolean launchTaskBehind,
-            boolean alwaysFocusable) {
-        return new AppWindowToken(service, token, mActivityComponent, voiceInteraction, dc,
-                inputDispatchingTimeoutNanos, fullscreen, showForAllUsers, targetSdk, orientation,
-                rotationAnimationHint, launchTaskBehind, alwaysFocusable,
-                this);
-    }
-
     void removeWindowContainer() {
-        if (mAtmService.mWindowManager.mRoot == null) return;
+        if (mWmService.mRoot == null) return;
 
-        final DisplayContent dc = mAtmService.mWindowManager.mRoot.getDisplayContent(
-                getDisplayId());
+        final DisplayContent dc = mWmService.mRoot.getDisplayContent(getDisplayId());
         if (dc == null) {
             Slog.w(TAG, "removeWindowContainer: Attempted to remove token: "
                     + appToken + " from non-existing displayId=" + getDisplayId());
@@ -1256,7 +1127,7 @@
      * should ensure that the {@param newTask} is not already the parent of this activity.
      */
     void reparent(TaskRecord newTask, int position, String reason) {
-        if (mAppWindowToken == null) {
+        if (getParent() == null) {
             Slog.w(TAG, "reparent: Attempted to reparent non-existing app token: " + appToken);
             return;
         }
@@ -1275,7 +1146,7 @@
                     + " r=" + this + " (" + prevTask.getStackId() + ")");
         }
 
-        mAppWindowToken.reparent(newTask.getTask(), position);
+        reparent(newTask.getTask(), position);
 
         // 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.
@@ -1366,6 +1237,7 @@
     /**
      * @return Stack value from current task, null if there is no task.
      */
+    // TODO: Remove once ActivityStack and TaskStack are unified.
     <T extends ActivityStack> T getActivityStack() {
         return task != null ? (T) task.getStack() : null;
     }
@@ -1380,14 +1252,13 @@
     }
 
     boolean setOccludesParent(boolean occludesParent) {
-        final boolean changed = mAppWindowToken.setOccludesParent(occludesParent);
+        final boolean changed = super.setOccludesParent(occludesParent);
         if (changed) {
             if (!occludesParent) {
                 getActivityStack().convertActivityToTranslucent(this);
             }
             // Keep track of the number of fullscreen activities in this task.
             task.numFullscreen += occludesParent ? +1 : -1;
-            fullscreen = occludesParent;
         }
         // Always ensure visibility if this activity doesn't occlude parent, so the
         // {@link #returningOptions} of the activity under this one can be applied in
@@ -1556,10 +1427,6 @@
                 OP_PICTURE_IN_PICTURE, info.applicationInfo.uid, packageName) == MODE_ALLOWED;
     }
 
-    boolean isAlwaysFocusable() {
-        return (info.flags & FLAG_ALWAYS_FOCUSABLE) != 0;
-    }
-
     /** Move activity with its stack to front and make the stack focused. */
     boolean moveFocusableActivityToTop(String reason) {
         if (!isFocusable()) {
@@ -1707,7 +1574,7 @@
             final TaskRecord task = getTaskRecord();
             EventLog.writeEvent(EventLogTags.AM_FINISH_ACTIVITY,
                     mUserId, System.identityHashCode(this),
-                    task.taskId, shortComponentName, reason);
+                    task.mTaskId, shortComponentName, reason);
             final ArrayList<ActivityRecord> activities = task.mActivities;
             final int index = activities.indexOf(this);
             if (index < (activities.size() - 1)) {
@@ -1856,25 +1723,27 @@
         // implied that the current finishing activity should be added into stopping list rather
         // than destroy immediately.
         final boolean isNextNotYetVisible = next != null && (!next.nowVisible || !next.visible);
-        final ActivityStack stack = getActivityStack();
-        final boolean notFocusedStack = stack != mRootActivityContainer.getTopDisplayFocusedStack();
+        final boolean notGlobalFocusedStack =
+                getActivityStack() != mRootActivityContainer.getTopDisplayFocusedStack();
         if (isVisible && isNextNotYetVisible) {
+            // Add this activity to the list of stopping activities. It will be processed and
+            // destroyed when the next activity reports idle.
             addToStopping(false /* scheduleIdle */, false /* idleDelayed */,
                     "completeFinishing");
-            if (DEBUG_STATES) {
-                Slog.v(TAG_STATES, "Moving to STOPPING: " + this + " (finish requested)");
-            }
             setState(STOPPING, "completeFinishing");
-            if (notFocusedStack) {
+            if (notGlobalFocusedStack) {
+                // Ensuring visibility and configuration only for non-focused stacks since this
+                // method call is relatively expensive and not necessary for focused stacks.
                 mRootActivityContainer.ensureVisibilityAndConfig(next, getDisplayId(),
                         false /* markFrozenIfConfigChanged */, true /* deferResume */);
             }
-        } else if (isVisible && isState(PAUSED) && getActivityStack().isFocusedStackOnDisplay()
-                && !inPinnedWindowingMode()) {
-            // TODO(b/137329632): Currently non-focused stack is handled differently.
-            addToFinishingAndWaitForIdle();
+        } else if (addToFinishingAndWaitForIdle()) {
+            // We added this activity to the finishing list and something else is becoming resumed.
+            // The activity will complete finishing when the next activity reports idle. No need to
+            // do anything else here.
         } else {
-            // Not waiting for the next one to become visible - finish right away.
+            // Not waiting for the next one to become visible, and nothing else will be resumed in
+            // place of this activity - requesting destruction right away.
             activityRemoved = destroyIfPossible(reason);
         }
 
@@ -1931,13 +1800,20 @@
         return activityRemoved;
     }
 
+    /**
+     * Add this activity to the list of finishing and trigger resuming of activities in focused
+     * stacks.
+     * @return {@code true} if some other activity is being resumed as a result of this call.
+     */
     @VisibleForTesting
-    void addToFinishingAndWaitForIdle() {
+    boolean addToFinishingAndWaitForIdle() {
         if (DEBUG_STATES) Slog.v(TAG, "Enqueueing pending finish: " + this);
         setState(FINISHING, "addToFinishingAndWaitForIdle");
-        mStackSupervisor.mFinishingActivities.add(this);
+        if (!mStackSupervisor.mFinishingActivities.contains(this)) {
+            mStackSupervisor.mFinishingActivities.add(this);
+        }
         resumeKeyDispatchingLocked();
-        mRootActivityContainer.resumeFocusedStacksTopActivities();
+        return mRootActivityContainer.resumeFocusedStacksTopActivities();
     }
 
     /**
@@ -1967,7 +1843,7 @@
         }
 
         EventLog.writeEvent(EventLogTags.AM_DESTROY_ACTIVITY, mUserId,
-                System.identityHashCode(this), getTaskRecord().taskId, shortComponentName, reason);
+                System.identityHashCode(this), getTaskRecord().mTaskId, shortComponentName, reason);
 
         boolean removedFromHistory = false;
 
@@ -2105,7 +1981,7 @@
                 // work.
                 // TODO: If the callers to removeTask() changes such that we have multiple places
                 //       where we are destroying the task, move this back into removeTask()
-                mStackSupervisor.removeTaskByIdLocked(task.taskId, false /* killProcess */,
+                mStackSupervisor.removeTaskByIdLocked(task.mTaskId, false /* killProcess */,
                         !REMOVE_FROM_RECENTS, reason);
             }
 
@@ -2200,9 +2076,7 @@
         stack.removeTimeoutsForActivity(this);
         // Clean-up activities are no longer relaunching (e.g. app process died). Notify window
         // manager so it can update its bookkeeping.
-        if (mAppWindowToken != null) {
-            mAppWindowToken.clearRelaunching();
-        }
+        clearRelaunching();
     }
 
     /**
@@ -2221,7 +2095,7 @@
         final String strData = data != null ? data.toSafeString() : null;
 
         EventLog.writeEvent(tag,
-                mUserId, System.identityHashCode(this), task.taskId,
+                mUserId, System.identityHashCode(this), task.mTaskId,
                 shortComponentName, intent.getAction(),
                 intent.getType(), strData, intent.getFlags());
     }
@@ -2368,7 +2242,7 @@
      */
     void applyOptionsLocked(ActivityOptions pendingOptions, Intent intent) {
         final int animationType = pendingOptions.getAnimationType();
-        final DisplayContent displayContent = mAppWindowToken.getDisplayContent();
+        final DisplayContent displayContent = getDisplayContent();
         switch (animationType) {
             case ANIM_CUSTOM:
                 displayContent.mAppTransition.overridePendingAppTransition(
@@ -2502,11 +2376,8 @@
         if (!keysPaused) {
             keysPaused = true;
 
-            // TODO: remove the check after unification with AppWindowToken. The DC check is not
-            // needed after no mock mAppWindowToken in tests.
-            if (mAppWindowToken != null && mAppWindowToken.getDisplayContent() != null) {
-                mAppWindowToken.getDisplayContent().getInputMonitor().pauseDispatchingLw(
-                        mAppWindowToken);
+            if (getDisplayContent() != null) {
+                getDisplayContent().getInputMonitor().pauseDispatchingLw(this);
             }
         }
     }
@@ -2515,11 +2386,8 @@
         if (keysPaused) {
             keysPaused = false;
 
-            // TODO: remove the check after unification with AppWindowToken. The DC check is not
-            // needed after no mock mAppWindowToken in tests.
-            if (mAppWindowToken != null && mAppWindowToken.getDisplayContent() != null) {
-                mAppWindowToken.getDisplayContent().getInputMonitor().resumeDispatchingLw(
-                        mAppWindowToken);
+            if (getDisplayContent() != null) {
+                getDisplayContent().getInputMonitor().resumeDispatchingLw(this);
             }
         }
     }
@@ -2541,12 +2409,12 @@
     }
 
     void setVisibility(boolean visible) {
-        if (mAppWindowToken == null) {
+        if (getParent() == null) {
             Slog.w(TAG_WM, "Attempted to set visibility of non-existing app token: "
                     + appToken);
             return;
         }
-        mAppWindowToken.setVisibility(visible, mDeferHidingClient);
+        setVisibility(visible, mDeferHidingClient);
         mAtmService.addWindowLayoutReasons(
                 ActivityTaskManagerService.LAYOUT_REASON_VISIBILITY_CHANGED);
         mStackSupervisor.getActivityMetricsLogger().notifyVisibilityChanged(this);
@@ -2582,12 +2450,12 @@
         // an indication that the Surface will eventually be destroyed.
         // This however isn't necessarily true if we are going to sleep.
         if (state == STOPPING && !isSleeping()) {
-            if (mAppWindowToken == null) {
+            if (getParent() == null) {
                 Slog.w(TAG_WM, "Attempted to notify stopping on non-existing app token: "
                         + appToken);
                 return;
             }
-            mAppWindowToken.detachChildren();
+            detachChildren();
         }
 
         if (state == RESUMED) {
@@ -2646,23 +2514,20 @@
     }
 
     void notifyAppResumed(boolean wasStopped) {
-        if (mAppWindowToken == null) {
+        if (getParent() == null) {
             Slog.w(TAG_WM, "Attempted to notify resumed of non-existing app token: "
                     + appToken);
             return;
         }
-        mAppWindowToken.notifyAppResumed(wasStopped);
+        super.notifyAppResumed(wasStopped);
     }
 
     void notifyUnknownVisibilityLaunched() {
 
         // No display activities never add a window, so there is no point in waiting them for
         // relayout.
-        if (!noDisplay) {
-            if (mAppWindowToken != null) {
-                mAppWindowToken.getDisplayContent().mUnknownAppVisibilityController
-                        .notifyLaunched(mAppWindowToken);
-            }
+        if (!noDisplay && getDisplayContent() != null) {
+            getDisplayContent().mUnknownAppVisibilityController.notifyLaunched(this);
         }
     }
 
@@ -2962,10 +2827,7 @@
             display.handleActivitySizeCompatModeIfNeeded(r);
         }
 
-        if (r.mAppWindowToken != null) {
-            r.mAppWindowToken.getDisplayContent().mUnknownAppVisibilityController
-                    .notifyAppResumedFinished(r.mAppWindowToken);
-        }
+        r.getDisplayContent().mUnknownAppVisibilityController.notifyAppResumedFinished(r);
     }
 
     /**
@@ -3113,9 +2975,7 @@
                 setState(STOPPED, "activityStoppedLocked");
             }
 
-            if (mAppWindowToken != null) {
-                mAppWindowToken.notifyAppStopped();
-            }
+            notifyAppStopped();
 
             if (finishing) {
                 clearOptionsLocked();
@@ -3192,9 +3052,11 @@
         stack.removeLaunchTickMessages();
     }
 
-    // IApplicationToken
+    boolean mayFreezeScreenLocked() {
+        return mayFreezeScreenLocked(app);
+    }
 
-    public boolean mayFreezeScreenLocked(WindowProcessController app) {
+    private boolean mayFreezeScreenLocked(WindowProcessController app) {
         // Only freeze the screen if this activity is currently attached to
         // an application, and that application is not blocked or unresponding.
         // In any other case, we can't count on getting the screen unfrozen,
@@ -3202,9 +3064,13 @@
         return hasProcess() && !app.isCrashing() && !app.isNotResponding();
     }
 
-    public void startFreezingScreenLocked(WindowProcessController app, int configChanges) {
+    void startFreezingScreenLocked(int configChanges) {
+        startFreezingScreenLocked(app, configChanges);
+    }
+
+    void startFreezingScreenLocked(WindowProcessController app, int configChanges) {
         if (mayFreezeScreenLocked(app)) {
-            if (mAppWindowToken == null) {
+            if (getParent() == null) {
                 Slog.w(TAG_WM,
                         "Attempted to freeze screen with non-existing app token: " + appToken);
                 return;
@@ -3212,29 +3078,29 @@
 
             // Window configuration changes only effect windows, so don't require a screen freeze.
             int freezableConfigChanges = configChanges & ~(CONFIG_WINDOW_CONFIGURATION);
-            if (freezableConfigChanges == 0 && mAppWindowToken.okToDisplay()) {
+            if (freezableConfigChanges == 0 && okToDisplay()) {
                 ProtoLog.v(WM_DEBUG_ORIENTATION, "Skipping set freeze of %s", appToken);
                 return;
             }
 
-            mAppWindowToken.startFreezingScreen();
+            startFreezingScreen();
         }
     }
 
-    public void stopFreezingScreenLocked(boolean force) {
+    void stopFreezingScreenLocked(boolean force) {
         if (force || frozenBeforeDestroy) {
             frozenBeforeDestroy = false;
-            if (mAppWindowToken == null) {
+            if (getParent() == null) {
                 return;
             }
             ProtoLog.v(WM_DEBUG_ORIENTATION,
                         "Clear freezing of %s: hidden=%b freezing=%b", appToken,
-                                mAppWindowToken.isHidden(), mAppWindowToken.isFreezingScreen());
-            mAppWindowToken.stopFreezingScreen(true, force);
+                                isHidden(), isFreezingScreen());
+            stopFreezingScreen(true, force);
         }
     }
 
-    public void reportFullyDrawnLocked(boolean restoredFromBundle) {
+    void reportFullyDrawnLocked(boolean restoredFromBundle) {
         final WindowingModeTransitionInfoSnapshot info = mStackSupervisor
                 .getActivityMetricsLogger().logAppTransitionReportedDrawn(this, restoredFromBundle);
         if (info != null) {
@@ -3243,74 +3109,42 @@
         }
     }
 
-    /**
-     * Called when the starting window for this container is drawn.
-     */
-    public void onStartingWindowDrawn(long timestamp) {
-        synchronized (mAtmService.mGlobalLock) {
-            mStackSupervisor.getActivityMetricsLogger().notifyStartingWindowDrawn(
-                    getWindowingMode(), timestamp);
-        }
-    }
-
     /** Called when the windows associated app window container are drawn. */
-    public void onWindowsDrawn(boolean drawn, long timestamp) {
-        synchronized (mAtmService.mGlobalLock) {
-            mDrawn = drawn;
-            if (!drawn) {
-                return;
-            }
-            final WindowingModeTransitionInfoSnapshot info = mStackSupervisor
-                    .getActivityMetricsLogger().notifyWindowsDrawn(getWindowingMode(), timestamp);
-            final int windowsDrawnDelayMs = info != null ? info.windowsDrawnDelayMs : INVALID_DELAY;
-            final @LaunchState int launchState = info != null ? info.getLaunchState() : -1;
-            mStackSupervisor.reportActivityLaunchedLocked(false /* timeout */, this,
-                    windowsDrawnDelayMs, launchState);
-            mStackSupervisor.stopWaitingForActivityVisible(this);
-            finishLaunchTickingLocked();
-            if (task != null) {
-                task.hasBeenVisible = true;
-            }
+    void onWindowsDrawn(boolean drawn, long timestamp) {
+        mDrawn = drawn;
+        if (!drawn) {
+            return;
+        }
+        final WindowingModeTransitionInfoSnapshot info = mStackSupervisor
+                .getActivityMetricsLogger().notifyWindowsDrawn(getWindowingMode(), timestamp);
+        final int windowsDrawnDelayMs = info != null ? info.windowsDrawnDelayMs : INVALID_DELAY;
+        final @LaunchState int launchState = info != null ? info.getLaunchState() : -1;
+        mStackSupervisor.reportActivityLaunchedLocked(false /* timeout */, this,
+                windowsDrawnDelayMs, launchState);
+        mStackSupervisor.stopWaitingForActivityVisible(this);
+        finishLaunchTickingLocked();
+        if (task != null) {
+            task.hasBeenVisible = true;
         }
     }
 
     /** Called when the windows associated app window container are visible. */
-    public void onWindowsVisible() {
-        synchronized (mAtmService.mGlobalLock) {
-            mStackSupervisor.stopWaitingForActivityVisible(this);
-            if (DEBUG_SWITCH) Log.v(TAG_SWITCH, "windowsVisibleLocked(): " + this);
-            if (!nowVisible) {
-                nowVisible = true;
-                lastVisibleTime = SystemClock.uptimeMillis();
-                mAtmService.scheduleAppGcsLocked();
-            }
+    void onWindowsVisible() {
+        super.onWindowsVisible();
+        mStackSupervisor.stopWaitingForActivityVisible(this);
+        if (DEBUG_SWITCH) Log.v(TAG_SWITCH, "windowsVisibleLocked(): " + this);
+        if (!nowVisible) {
+            nowVisible = true;
+            lastVisibleTime = SystemClock.uptimeMillis();
+            mAtmService.scheduleAppGcsLocked();
         }
     }
 
     /** Called when the windows associated app window container are no longer visible. */
-    public void onWindowsGone() {
-        synchronized (mAtmService.mGlobalLock) {
-            if (DEBUG_SWITCH) Log.v(TAG_SWITCH, "windowsGone(): " + this);
-            nowVisible = false;
-        }
-    }
-
-    void onAnimationFinished() {
-        if (mRootActivityContainer.allResumedActivitiesIdle()
-                || 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 (mStackSupervisor.mStoppingActivities.contains(this)) {
-                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.
-            mStackSupervisor.processStoppingActivitiesLocked(null /* idleActivity */,
-                    false /* remove */, true /* processPausingActivities */);
-        }
+    void onWindowsGone() {
+        super.onWindowsGone();
+        if (DEBUG_SWITCH) Log.v(TAG_SWITCH, "windowsGone(): " + this);
+        nowVisible = false;
     }
 
     /**
@@ -3415,7 +3249,7 @@
                 || (onlyRoot && activityNdx > task.findRootIndex(true /* effectiveRoot */))) {
             return INVALID_TASK_ID;
         }
-        return task.taskId;
+        return task.mTaskId;
     }
 
     static ActivityRecord isInStackLocked(IBinder token) {
@@ -3470,8 +3304,8 @@
         Bitmap icon;
         if (_taskDescription.getIconFilename() == null &&
                 (icon = _taskDescription.getIcon()) != null) {
-            final String iconFilename = createImageFilename(createTime, task.taskId);
-            final File iconFile = new File(TaskPersister.getUserImagesDir(task.userId),
+            final String iconFilename = createImageFilename(createTime, task.mTaskId);
+            final File iconFile = new File(TaskPersister.getUserImagesDir(task.mUserId),
                     iconFilename);
             final String iconFilePath = iconFile.getAbsolutePath();
             mAtmService.getRecentTasks().saveImage(icon, iconFilePath);
@@ -3496,9 +3330,6 @@
 
     void showStartingWindow(ActivityRecord prev, boolean newTask, boolean taskSwitch,
             boolean fromRecents) {
-        if (mAppWindowToken == null) {
-            return;
-        }
         if (mTaskOverlay) {
             // We don't show starting window for overlay activities.
             return;
@@ -3526,26 +3357,20 @@
         if (mStartingWindowState == STARTING_WINDOW_SHOWN && behindFullscreenActivity) {
             if (DEBUG_VISIBILITY) Slog.w(TAG_VISIBILITY, "Found orphaned starting window " + this);
             mStartingWindowState = STARTING_WINDOW_REMOVED;
-            mAppWindowToken.removeStartingWindow();
+            removeStartingWindow();
         }
     }
 
     void setRequestedOrientation(int requestedOrientation) {
-        setOrientation(requestedOrientation, mayFreezeScreenLocked(app));
+        setOrientation(requestedOrientation, mayFreezeScreenLocked());
         mAtmService.getTaskChangeNotificationController().notifyActivityRequestedOrientationChanged(
-                task.taskId, requestedOrientation);
+                task.mTaskId, requestedOrientation);
     }
 
     private void setOrientation(int requestedOrientation, boolean freezeScreenIfNeeded) {
-        if (mAppWindowToken == null) {
-            Slog.w(TAG_WM,
-                    "Attempted to set orientation of non-existing app token: " + appToken);
-            return;
-        }
-
         final IBinder binder =
                 (freezeScreenIfNeeded && appToken != null) ? appToken.asBinder() : null;
-        mAppWindowToken.setOrientation(requestedOrientation, binder, this);
+        setOrientation(requestedOrientation, binder, this);
 
         // Push the new configuration to the requested app in case where it's not pushed, e.g. when
         // the request is handled at task level with letterbox.
@@ -3555,23 +3380,6 @@
         }
     }
 
-    int getOrientation() {
-        if (mAppWindowToken == null) {
-            return info.screenOrientation;
-        }
-
-        return mAppWindowToken.getOrientationIgnoreVisibility();
-    }
-
-    void setDisablePreviewScreenshots(boolean disable) {
-        if (mAppWindowToken == null) {
-            Slog.w(TAG_WM, "Attempted to set disable screenshots of non-existing app"
-                    + " token: " + appToken);
-            return;
-        }
-        mAppWindowToken.setDisablePreviewScreenshots(disable);
-    }
-
     /**
      * 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.
@@ -3594,33 +3402,6 @@
     }
 
     /**
-     * Get the configuration orientation by the requested screen orientation
-     * ({@link ActivityInfo.ScreenOrientation}) of this activity.
-     *
-     * @return orientation in ({@link Configuration#ORIENTATION_LANDSCAPE},
-     *         {@link Configuration#ORIENTATION_PORTRAIT},
-     *         {@link Configuration#ORIENTATION_UNDEFINED}).
-     */
-    int getRequestedConfigurationOrientation() {
-        final int screenOrientation = getOrientation();
-        if (screenOrientation == ActivityInfo.SCREEN_ORIENTATION_NOSENSOR) {
-            // NOSENSOR means the display's "natural" orientation, so return that.
-            final ActivityDisplay display = getDisplay();
-            if (display != null && display.mDisplayContent != null) {
-                return display.mDisplayContent.getNaturalOrientation();
-            }
-        } else if (screenOrientation == ActivityInfo.SCREEN_ORIENTATION_LOCKED) {
-            // LOCKED means the activity's orientation remains unchanged, so return existing value.
-            return getConfiguration().orientation;
-        } else if (isFixedOrientationLandscape(screenOrientation)) {
-            return ORIENTATION_LANDSCAPE;
-        } else if (isFixedOrientationPortrait(screenOrientation)) {
-            return ORIENTATION_PORTRAIT;
-        }
-        return ORIENTATION_UNDEFINED;
-    }
-
-    /**
      * @return {@code true} if this activity is in size compatibility mode that uses the different
      *         density or bounds from its parent.
      */
@@ -3701,6 +3482,8 @@
     // TODO(b/36505427): Consider moving this method and similar ones to ConfigurationContainer.
     private void updateOverrideConfiguration() {
         final Configuration overrideConfig = mTmpConfig;
+        overrideConfig.setTo(getRequestedOverrideConfiguration());
+
         if (shouldUseSizeCompatMode()) {
             if (mCompatDisplayInsets != null) {
                 // The override configuration is set only once in size compatibility mode.
@@ -3719,7 +3502,6 @@
             // are relative to bounds and density, they will be calculated in
             // {@link TaskRecord#computeConfigResourceOverrides} and the result will also be
             // relatively fixed.
-            overrideConfig.unset();
             overrideConfig.colorMode = parentConfig.colorMode;
             overrideConfig.densityDpi = parentConfig.densityDpi;
             overrideConfig.screenLayout = parentConfig.screenLayout
@@ -3746,7 +3528,6 @@
                 return;
             }
 
-            overrideConfig.unset();
             overrideConfig.windowConfiguration.setBounds(mTmpBounds);
         }
 
@@ -3873,22 +3654,6 @@
             onMergedOverrideConfigurationChanged();
         }
 
-        // TODO(b/80414790): Remove code below after unification.
-        // Same as above it doesn't notify configuration listeners, and consequently AppWindowToken
-        // can't get updated seq number. However WindowState's merged override configuration needs
-        // to have this seq number because that's also used for activity config pushes during layout
-        // traversal. Therefore explicitly update them here.
-        if (mAppWindowToken == null) {
-            return;
-        }
-        final Configuration appWindowTokenRequestedOverrideConfig =
-                mAppWindowToken.getRequestedOverrideConfiguration();
-        if (appWindowTokenRequestedOverrideConfig.seq != getResolvedOverrideConfiguration().seq) {
-            appWindowTokenRequestedOverrideConfig.seq =
-                    getResolvedOverrideConfiguration().seq;
-            mAppWindowToken.onMergedOverrideConfigurationChanged();
-        }
-
         final ActivityDisplay display = getDisplay();
         if (display == null) {
             return;
@@ -3916,7 +3681,7 @@
 
     /** Returns true if the configuration is compatible with this activity. */
     boolean isConfigurationCompatible(Configuration config) {
-        final int orientation = getOrientation();
+        final int orientation = getRequestedOrientation();
         if (isFixedOrientationPortrait(orientation)
                 && config.orientation != ORIENTATION_PORTRAIT) {
             return false;
@@ -4149,7 +3914,7 @@
         if (shouldRelaunchLocked(changes, mTmpConfig) || forceNewConfig) {
             // Aha, the activity isn't handling the change, so DIE DIE DIE.
             configChangeFlags |= changes;
-            startFreezingScreenLocked(app, globalChanges);
+            startFreezingScreenLocked(globalChanges);
             forceNewConfig = false;
             preserveWindow &= isResizeOnlyChange(changes);
             final boolean hasResizeChange = hasResizeChange(changes & ~info.getRealConfigChanged());
@@ -4305,18 +4070,16 @@
                         + " preserveWindow=" + preserveWindow);
         EventLog.writeEvent(andResume ? AM_RELAUNCH_RESUME_ACTIVITY
                         : AM_RELAUNCH_ACTIVITY, mUserId, System.identityHashCode(this),
-                task.taskId, shortComponentName);
+                task.mTaskId, shortComponentName);
 
-        startFreezingScreenLocked(app, 0);
+        startFreezingScreenLocked(0);
 
         try {
             if (DEBUG_SWITCH || DEBUG_STATES) Slog.i(TAG_SWITCH,
                     "Moving to " + (andResume ? "RESUMED" : "PAUSED") + " Relaunching " + this
                             + " callers=" + Debug.getCallers(6));
             forceNewConfig = false;
-            if (mAppWindowToken != null) {
-                mAppWindowToken.startRelaunching();
-            }
+            startRelaunching();
             final ClientTransactionItem callbackItem = ActivityRelaunchItem.obtain(pendingResults,
                     pendingNewIntents, configChangeFlags,
                     new MergedConfiguration(mAtmService.getGlobalConfiguration(),
@@ -4405,8 +4168,8 @@
             return;
         }
 
-        if (mAppWindowToken != null) {
-            mAppWindowToken.startFreezingScreen();
+        if (getParent() != null) {
+            startFreezingScreen();
         }
         // The process will be killed until the activity reports stopped with saved state (see
         // {@link ActivityTaskManagerService.activityStopped}).
@@ -4574,67 +4337,24 @@
         return info.applicationInfo.uid;
     }
 
-    void setShowWhenLocked(boolean showWhenLocked) {
-        mShowWhenLocked = showWhenLocked;
-        mRootActivityContainer.ensureActivitiesVisible(null, 0 /* configChanges */,
-                false /* preserveWindows */);
-    }
-
-    void setInheritShowWhenLocked(boolean inheritShowWhenLocked) {
-        mInheritShownWhenLocked = inheritShowWhenLocked;
-        mRootActivityContainer.ensureActivitiesVisible(null, 0, false);
-    }
-
-    /**
-     * @return 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 true is returned.
-     */
-    boolean canShowWhenLocked() {
-        if (!inPinnedWindowingMode() && (mShowWhenLocked
-                || (mAppWindowToken != null && mAppWindowToken.containsShowWhenLockedWindow()))) {
-            return true;
-        } else if (mInheritShownWhenLocked) {
-            ActivityRecord r = getActivityBelow();
-            return r != null && !r.inPinnedWindowingMode() && (r.mShowWhenLocked
-                    || (r.mAppWindowToken != null
-                        && r.mAppWindowToken.containsShowWhenLockedWindow()));
-        } else {
-            return false;
-        }
-    }
-
-    /**
-     * @return an {@link ActivityRecord} of the activity below this activity, or {@code null} if no
-     * such activity exists.
-     */
-    @Nullable
-    private ActivityRecord getActivityBelow() {
-        final int pos = task.mActivities.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;
+    @Override
+    int getPid() {
+        return app != null ? app.getPid() : 0;
     }
 
     /**
      * Determines whether this ActivityRecord can turn the screen on. It checks whether the flag
-     * {@link #mTurnScreenOn} is set and checks whether the ActivityRecord should be visible
-     * depending on Keyguard state
+     * {@link AppWindowToken#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.
      */
     boolean canTurnScreenOn() {
+        if (!getTurnScreenOnFlag()) {
+            return false;
+        }
         final ActivityStack stack = getActivityStack();
-        return mTurnScreenOn && stack != null &&
+        return stack != null &&
                 stack.checkKeyguardVisibility(this, true /* shouldBeVisible */, true /* isTop */);
     }
 
@@ -4648,10 +4368,6 @@
         return app == null || app.updateTopResumingActivityInProcessIfNeeded(this);
     }
 
-    boolean getTurnScreenOnFlag() {
-        return mTurnScreenOn;
-    }
-
     boolean isTopRunningActivity() {
         return mRootActivityContainer.topRunningActivity() == this;
     }
@@ -4686,20 +4402,11 @@
         return task.getChildAt(0) == this;
     }
 
-    void registerRemoteAnimations(RemoteAnimationDefinition definition) {
-        if (mAppWindowToken == null) {
-            Slog.w(TAG_WM, "Attempted to register remote animations with non-existing app"
-                    + " token: " + appToken);
-            return;
-        }
-        mAppWindowToken.registerRemoteAnimations(definition);
-    }
-
     @Override
     public String toString() {
         if (stringName != null) {
-            return stringName + " t" + (task == null ? INVALID_TASK_ID : task.taskId) +
-                    (finishing ? " f}" : "}");
+            return stringName + " t" + (task == null ? INVALID_TASK_ID : task.mTaskId) +
+                    (finishing ? " f}" : "") + (mIsExiting ? " mIsExiting=" : "") + "}";
         }
         StringBuilder sb = new StringBuilder(128);
         sb.append("ActivityRecord{");
@@ -4709,15 +4416,7 @@
         sb.append(' ');
         sb.append(intent.getComponent().flattenToShortString());
         stringName = sb.toString();
-        return toString();
-    }
-
-    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);
+        return stringName;
     }
 
     /**
@@ -4725,7 +4424,7 @@
      * {@code ActivityRecordProto} is the outer-most proto data.
      */
     void writeToProto(ProtoOutputStream proto) {
-        super.writeToProto(proto, CONFIGURATION_CONTAINER, WindowTraceLogLevel.ALL);
+        super.writeToProto(proto, APP_WINDOW_TOKEN, WindowTraceLogLevel.ALL);
         writeIdentifierToProto(proto, IDENTIFIER);
         proto.write(STATE, mState.toString());
         proto.write(VISIBLE, visible);
@@ -4733,7 +4432,7 @@
         if (hasProcess()) {
             proto.write(PROC_ID, app.getPid());
         }
-        proto.write(TRANSLUCENT, !fullscreen);
+        proto.write(TRANSLUCENT, !occludesParent());
     }
 
     public void writeToProto(ProtoOutputStream proto, long fieldId) {
diff --git a/services/core/java/com/android/server/wm/ActivityStack.java b/services/core/java/com/android/server/wm/ActivityStack.java
index ab1f258..5959254 100644
--- a/services/core/java/com/android/server/wm/ActivityStack.java
+++ b/services/core/java/com/android/server/wm/ActivityStack.java
@@ -775,7 +775,7 @@
             // multi-window mode.
             final String packageName = topActivity.info.applicationInfo.packageName;
             mService.getTaskChangeNotificationController().notifyActivityForcedResizable(
-                    topTask.taskId, FORCED_RESIZEABLE_REASON_SPLIT_SCREEN, packageName);
+                    topTask.mTaskId, FORCED_RESIZEABLE_REASON_SPLIT_SCREEN, packageName);
         }
 
         mService.deferWindowLayout();
@@ -1114,7 +1114,7 @@
     final ActivityRecord topRunningActivityLocked(IBinder token, int taskId) {
         for (int taskNdx = mTaskHistory.size() - 1; taskNdx >= 0; --taskNdx) {
             TaskRecord task = mTaskHistory.get(taskNdx);
-            if (task.taskId == taskId) {
+            if (task.mTaskId == taskId) {
                 continue;
             }
             ArrayList<ActivityRecord> activities = task.mActivities;
@@ -1150,7 +1150,7 @@
     TaskRecord taskForIdLocked(int id) {
         for (int taskNdx = mTaskHistory.size() - 1; taskNdx >= 0; --taskNdx) {
             final TaskRecord task = mTaskHistory.get(taskNdx);
-            if (task.taskId == id) {
+            if (task.mTaskId == id) {
                 return task;
             }
         }
@@ -1345,7 +1345,7 @@
                 if (DEBUG_TASKS) Slog.d(TAG_TASKS, "Skipping " + task + ": voice session");
                 continue;
             }
-            if (task.userId != userId) {
+            if (task.mUserId != userId) {
                 // Looking for a different task.
                 if (DEBUG_TASKS) Slog.d(TAG_TASKS, "Skipping " + task + ": different user");
                 continue;
@@ -1896,7 +1896,7 @@
                     continue;
                 }
 
-                if (r.fullscreen || r.hasWallpaper) {
+                if (r.occludesParent() || r.hasWallpaper) {
                     // Stack isn't translucent if it has at least one fullscreen activity
                     // that is visible.
                     return false;
@@ -2259,8 +2259,7 @@
                 .isKeyguardOrAodShowing(displayId);
         final boolean keyguardLocked = mStackSupervisor.getKeyguardController().isKeyguardLocked();
         final boolean showWhenLocked = r.canShowWhenLocked();
-        final boolean dismissKeyguard = r.mAppWindowToken != null
-                && r.mAppWindowToken.containsDismissKeyguardWindow();
+        final boolean dismissKeyguard = r.containsDismissKeyguardWindow();
         if (shouldBeVisible) {
             if (dismissKeyguard && mTopDismissingKeyguardActivity == null) {
                 mTopDismissingKeyguardActivity = r;
@@ -2329,7 +2328,7 @@
             // get it started and resume if no other stack in this stack is resumed.
             if (DEBUG_VISIBILITY) Slog.v(TAG_VISIBILITY, "Start and freeze screen for " + r);
             if (r != starting) {
-                r.startFreezingScreenLocked(r.app, configChanges);
+                r.startFreezingScreenLocked(configChanges);
             }
             if (!r.visible || r.mLaunchTaskBehind) {
                 if (DEBUG_VISIBILITY) Slog.v(TAG_VISIBILITY, "Starting and making visible: " + r);
@@ -2345,7 +2344,7 @@
 
     private boolean updateBehindFullscreen(boolean stackInvisible, boolean behindFullscreenActivity,
             ActivityRecord r) {
-        if (r.fullscreen) {
+        if (r.occludesParent()) {
             if (DEBUG_VISIBILITY) Slog.v(TAG_VISIBILITY, "Fullscreen: at " + r
                         + " stackInvisible=" + stackInvisible
                         + " behindFullscreenActivity=" + behindFullscreenActivity);
@@ -2431,12 +2430,12 @@
                     if (r == topActivity) {
                         aboveTop = false;
                     }
-                    behindFullscreenActivity |= r.fullscreen;
+                    behindFullscreenActivity |= r.occludesParent();
                     continue;
                 }
 
                 r.removeOrphanedStartingWindow(behindFullscreenActivity);
-                behindFullscreenActivity |= r.fullscreen;
+                behindFullscreenActivity |= r.occludesParent();
             }
         }
     }
@@ -2566,8 +2565,7 @@
                 final boolean canShowWhenLocked = !mTopActivityOccludesKeyguard
                         && next.canShowWhenLocked();
                 final boolean mayDismissKeyguard = mTopDismissingKeyguardActivity != next
-                        && next.mAppWindowToken != null
-                        && next.mAppWindowToken.containsDismissKeyguardWindow();
+                        && next.containsDismissKeyguardWindow();
 
                 if (canShowWhenLocked || mayDismissKeyguard) {
                     ensureActivitiesVisibleLocked(null /* starting */, 0 /* configChanges */,
@@ -2776,7 +2774,7 @@
             final boolean lastActivityTranslucent = lastFocusedStack != null
                     && (lastFocusedStack.inMultiWindowMode()
                     || (lastFocusedStack.mLastPausedActivity != null
-                    && !lastFocusedStack.mLastPausedActivity.fullscreen));
+                    && !lastFocusedStack.mLastPausedActivity.occludesParent()));
 
             // This activity is now becoming visible.
             if (!next.visible || next.stopped || lastActivityTranslucent) {
@@ -2865,7 +2863,7 @@
                 next.notifyAppResumed(next.stopped);
 
                 EventLog.writeEvent(EventLogTags.AM_RESUME_ACTIVITY, next.mUserId,
-                        System.identityHashCode(next), next.getTaskRecord().taskId,
+                        System.identityHashCode(next), next.getTaskRecord().mTaskId,
                         next.shortComponentName);
 
                 next.sleeping = false;
@@ -2975,7 +2973,7 @@
         // The task can't be shown, put non-current user tasks below current user tasks.
         while (maxPosition > 0) {
             final TaskRecord tmpTask = mTaskHistory.get(maxPosition - 1);
-            if (!mStackSupervisor.isCurrentProfileLocked(tmpTask.userId)
+            if (!mStackSupervisor.isCurrentProfileLocked(tmpTask.mUserId)
                     || tmpTask.topRunningActivityLocked() == null) {
                 break;
             }
@@ -3028,7 +3026,7 @@
     void startActivityLocked(ActivityRecord r, ActivityRecord focusedTopActivity,
             boolean newTask, boolean keepCurTransition, ActivityOptions options) {
         TaskRecord rTask = r.getTaskRecord();
-        final int taskId = rTask.taskId;
+        final int taskId = rTask.mTaskId;
         final boolean allowMoveToFront = options == null || !options.getAvoidMoveToFront();
         // mLaunchTaskBehind tasks get placed at the back of the task stack.
         if (!r.mLaunchTaskBehind && allowMoveToFront
@@ -3055,7 +3053,7 @@
                     if (!startIt) {
                         if (DEBUG_ADD_REMOVE) Slog.i(TAG, "Adding activity " + r + " to task "
                                 + task, new RuntimeException("here").fillInStackTrace());
-                        r.createAppWindowToken();
+                        r.setTask(rTask);
                         ActivityOptions.abort(options);
                         return;
                     }
@@ -3082,12 +3080,7 @@
         // Slot the activity into the history stack and proceed
         if (DEBUG_ADD_REMOVE) Slog.i(TAG, "Adding activity " + r + " to stack to task " + task,
                 new RuntimeException("here").fillInStackTrace());
-        // TODO: Need to investigate if it is okay for the controller to already be created by the
-        // time we get to this point. I think it is, but need to double check.
-        // Use test in b/34179495 to trace the call path.
-        if (r.mAppWindowToken == null) {
-            r.createAppWindowToken();
-        }
+        r.setTask(task);
 
         // The transition animation and starting window are not needed if {@code allowMoveToFront}
         // is false, because the activity won't be visible.
@@ -3944,7 +3937,7 @@
                 if (r.finishing) {
                     continue;
                 }
-                if (r.fullscreen) {
+                if (r.occludesParent()) {
                     lastIsOpaque = true;
                 }
                 if (owner != null && r.app != owner) {
@@ -4105,7 +4098,7 @@
                             Slog.w(TAG, "Force removing " + r + ": app died, no saved state");
                             EventLog.writeEvent(EventLogTags.AM_FINISH_ACTIVITY,
                                     r.mUserId, System.identityHashCode(r),
-                                    r.getTaskRecord().taskId, r.shortComponentName,
+                                    r.getTaskRecord().mTaskId, r.shortComponentName,
                                     "proc died without state saved");
                         }
                     } else {
@@ -4230,7 +4223,7 @@
             }
 
             mRootActivityContainer.resumeFocusedStacksTopActivities();
-            EventLog.writeEvent(EventLogTags.AM_TASK_TO_FRONT, tr.userId, tr.taskId);
+            EventLog.writeEvent(EventLogTags.AM_TASK_TO_FRONT, tr.mUserId, tr.mTaskId);
             mService.getTaskChangeNotificationController().notifyTaskMovedToFront(tr.getTaskInfo());
         } finally {
             getDisplay().continueUpdateImeTarget();
@@ -4335,7 +4328,7 @@
                 final ActivityRecord r = activities.get(activityIndex);
                 updatedConfig |= r.ensureActivityConfiguration(0 /* globalChanges */,
                         preserveWindow);
-                if (r.fullscreen) {
+                if (r.occludesParent()) {
                     behindFullscreen = true;
                     break;
                 }
@@ -4438,7 +4431,7 @@
                 if (r.appToken == token) {
                     return true;
                 }
-                if (r.fullscreen && !r.finishing) {
+                if (r.occludesParent() && !r.finishing) {
                     return false;
                 }
             }
@@ -4527,7 +4520,7 @@
                 continue;
             }
             if (task.effectiveUid != callingUid) {
-                if (task.userId != userId && !crossUser && !profileIds.contains(task.userId)) {
+                if (task.mUserId != userId && !crossUser && !profileIds.contains(task.mUserId)) {
                     // Skip if the caller does not have cross user permission or cannot access
                     // the task's profile
                     continue;
@@ -4552,7 +4545,7 @@
                 // For the focused stack top task, update the last stack active time so that it can
                 // be used to determine the order of the tasks (it may not be set for newly created
                 // tasks)
-                task.lastActiveTime = SystemClock.elapsedRealtime();
+                task.touchActiveTime();
                 topTask = false;
             }
             tasksOut.add(task);
@@ -4661,7 +4654,7 @@
             if (needSep) {
                 pw.println("");
             }
-            pw.println(prefix + "Task id #" + task.taskId);
+            pw.println(prefix + "Task id #" + task.mTaskId);
             pw.println(prefix + "mBounds=" + task.getRequestedOverrideBounds());
             pw.println(prefix + "mMinWidth=" + task.mMinWidth);
             pw.println(prefix + "mMinHeight=" + task.mMinHeight);
@@ -4718,8 +4711,7 @@
                 if (a.info.packageName.equals(packageName)) {
                     a.forceNewConfig = true;
                     if (starting != null && a == starting && a.visible) {
-                        a.startFreezingScreenLocked(starting.app,
-                                CONFIG_SCREEN_LAYOUT);
+                        a.startFreezingScreenLocked(CONFIG_SCREEN_LAYOUT);
                     }
                 }
             }
@@ -4740,7 +4732,7 @@
         final boolean removed = mTaskHistory.remove(task);
 
         if (removed) {
-            EventLog.writeEvent(EventLogTags.AM_REMOVE_TASK, task.taskId, getStackId());
+            EventLog.writeEvent(EventLogTags.AM_REMOVE_TASK, task.mTaskId, getStackId());
         }
 
         removeActivitiesFromLRUList(task);
@@ -4892,7 +4884,7 @@
             mStackSupervisor.scheduleUpdatePictureInPictureModeIfNeeded(task, prevStack);
         } else if (task.voiceSession != null) {
             try {
-                task.voiceSession.taskStarted(task.intent, task.taskId);
+                task.voiceSession.taskStarted(task.intent, task.mTaskId);
             } catch (RemoteException e) {
             }
         }
@@ -4950,7 +4942,7 @@
             if (top != null && !top.isConfigurationCompatible(parentConfig)) {
                 // The final orientation of this activity will change after moving to full screen.
                 // Start freezing screen here to prevent showing a temporary full screen window.
-                top.startFreezingScreenLocked(top.app, CONFIG_SCREEN_LAYOUT);
+                top.startFreezingScreenLocked(CONFIG_SCREEN_LAYOUT);
                 mService.moveTasksToFullscreenStack(mStackId, true /* onTop */);
                 return;
             }
diff --git a/services/core/java/com/android/server/wm/ActivityStackSupervisor.java b/services/core/java/com/android/server/wm/ActivityStackSupervisor.java
index d151f86..f1284d81 100644
--- a/services/core/java/com/android/server/wm/ActivityStackSupervisor.java
+++ b/services/core/java/com/android/server/wm/ActivityStackSupervisor.java
@@ -821,7 +821,7 @@
                                 + " with results=" + results + " newIntents=" + newIntents
                                 + " andResume=" + andResume);
                 EventLog.writeEvent(EventLogTags.AM_RESTART_ACTIVITY, r.mUserId,
-                        System.identityHashCode(r), task.taskId, r.shortComponentName);
+                        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);
@@ -1765,7 +1765,7 @@
             moveTasksToFullscreenStackLocked(stack, !ON_TOP);
         } else {
             for (int i = tasks.size() - 1; i >= 0; i--) {
-                removeTaskByIdLocked(tasks.get(i).taskId, true /* killProcess */,
+                removeTaskByIdLocked(tasks.get(i).mTaskId, true /* killProcess */,
                         REMOVE_FROM_RECENTS, "remove-stack");
             }
         }
@@ -1817,7 +1817,7 @@
 
         // Find any running services associated with this app and stop if needed.
         final Message msg = PooledLambda.obtainMessage(ActivityManagerInternal::cleanUpServices,
-                mService.mAmInternal, tr.userId, component, new Intent(tr.getBaseIntent()));
+                mService.mAmInternal, tr.mUserId, component, new Intent(tr.getBaseIntent()));
         mService.mH.sendMessage(msg);
 
         if (!killProcess) {
@@ -1834,7 +1834,7 @@
             SparseArray<WindowProcessController> uids = pmap.valueAt(i);
             for (int j = 0; j < uids.size(); j++) {
                 WindowProcessController proc = uids.valueAt(j);
-                if (proc.mUserId != tr.userId) {
+                if (proc.mUserId != tr.mUserId) {
                     // Don't kill process for a different user.
                     continue;
                 }
@@ -1901,7 +1901,7 @@
                 "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).createAppWindowToken();
+            activities.get(activityNdx).setTask(task);
         }
         return true;
     }
@@ -1916,7 +1916,7 @@
         if (wasTrimmed) {
             // Task was trimmed from the recent tasks list -- remove the active task record as well
             // since the user won't really be able to go back to it
-            removeTaskByIdLocked(task.taskId, killProcess, false /* removeFromRecents */,
+            removeTaskByIdLocked(task.mTaskId, killProcess, false /* removeFromRecents */,
                     "recent-task-trimmed");
         }
         task.removedFromRecents();
@@ -2123,6 +2123,7 @@
         return false;
     }
 
+    // TODO: Change method name to reflect what it actually does.
     final ArrayList<ActivityRecord> processStoppingActivitiesLocked(ActivityRecord idleActivity,
             boolean remove, boolean processPausingActivities) {
         ArrayList<ActivityRecord> stops = null;
@@ -2131,7 +2132,7 @@
         for (int activityNdx = mStoppingActivities.size() - 1; activityNdx >= 0; --activityNdx) {
             ActivityRecord s = mStoppingActivities.get(activityNdx);
 
-            final boolean animating = s.mAppWindowToken.isSelfAnimating();
+            final boolean animating = s.isSelfAnimating();
 
             if (DEBUG_STATES) Slog.v(TAG, "Stopping " + s + ": nowVisible=" + nowVisible
                     + " animating=" + animating + " finishing=" + s.finishing);
@@ -2476,15 +2477,13 @@
             return;
         }
         mService.getTaskChangeNotificationController().notifyActivityForcedResizable(
-                task.taskId, reason, topActivity.info.applicationInfo.packageName);
+                task.mTaskId, reason, topActivity.info.applicationInfo.packageName);
     }
 
     void activityRelaunchedLocked(IBinder token) {
         final ActivityRecord r = ActivityRecord.isInStackLocked(token);
         if (r != null) {
-            if (r.mAppWindowToken != null) {
-                r.mAppWindowToken.finishRelaunching();
-            }
+            r.finishRelaunching();
             if (r.getActivityStack().shouldSleepOrShutDownActivities()) {
                 r.setSleeping(true, true);
             }
@@ -2700,7 +2699,7 @@
      * @param task The task to put into resizing mode
      */
     void setResizingDuringAnimation(TaskRecord task) {
-        mResizingTasksDuringAnimation.add(task.taskId);
+        mResizingTasksDuringAnimation.add(task.mTaskId);
         task.setTaskDockedResizing(true);
     }
 
@@ -2762,7 +2761,7 @@
 
             // If the user must confirm credentials (e.g. when first launching a work app and the
             // Work Challenge is present) let startActivityInPackage handle the intercepting.
-            if (!mService.mAmInternal.shouldConfirmCredentials(task.userId)
+            if (!mService.mAmInternal.shouldConfirmCredentials(task.mUserId)
                     && task.getRootActivity() != null) {
                 final ActivityRecord targetActivity = task.getTopActivity();
 
@@ -2771,7 +2770,7 @@
                 mActivityMetricsLogger.notifyActivityLaunching(task.intent);
                 try {
                     mService.moveTaskToFrontLocked(null /* appThread */, null /* callingPackage */,
-                            task.taskId, 0, options, true /* fromRecents */);
+                            task.mTaskId, 0, options, true /* fromRecents */);
                     // Apply options to prevent pendingOptions be taken by client to make sure
                     // the override pending app transition will be applied immediately.
                     targetActivity.applyOptionsLocked();
@@ -2788,7 +2787,7 @@
             callingPackage = task.mCallingPackage;
             intent = task.intent;
             intent.addFlags(Intent.FLAG_ACTIVITY_LAUNCHED_FROM_HISTORY);
-            userId = task.userId;
+            userId = task.mUserId;
             return mService.getActivityStartController().startActivityInPackage(
                     task.mCallingUid, callingPid, callingUid, callingPackage, intent, null, null,
                     null, 0, 0, options, userId, task, "startActivityFromRecents",
diff --git a/services/core/java/com/android/server/wm/ActivityStartController.java b/services/core/java/com/android/server/wm/ActivityStartController.java
index 919141c..6ee64f3 100644
--- a/services/core/java/com/android/server/wm/ActivityStartController.java
+++ b/services/core/java/com/android/server/wm/ActivityStartController.java
@@ -386,6 +386,8 @@
                     throw new IllegalArgumentException("File descriptors passed in Intent");
                 }
 
+                // Get the flag earlier because the intent may be modified in resolveActivity below.
+                final boolean componentSpecified = intent.getComponent() != null;
                 // Don't modify the client's object!
                 intent = new Intent(intent);
 
@@ -409,7 +411,6 @@
                         .setCaller(caller)
                         .setResolvedType(resolvedTypes[i])
                         .setActivityInfo(aInfo)
-                        .setResultTo(resultTo)
                         .setRequestCode(-1)
                         .setCallingPid(callingPid)
                         .setCallingUid(callingUid)
@@ -417,7 +418,7 @@
                         .setRealCallingPid(realCallingPid)
                         .setRealCallingUid(realCallingUid)
                         .setActivityOptions(checkedOptions)
-                        .setComponentSpecified(intent.getComponent() != null)
+                        .setComponentSpecified(componentSpecified)
 
                         // Top activity decides on animation being run, so we allow only for the
                         // top one as otherwise an activity below might consume it.
@@ -430,7 +431,8 @@
             // Lock the loop to ensure the activities launched in a sequence.
             synchronized (mService.mGlobalLock) {
                 for (int i = 0; i < starters.length; i++) {
-                    final int startResult = starters[i].setOutActivity(outActivity).execute();
+                    final int startResult = starters[i].setResultTo(resultTo)
+                            .setOutActivity(outActivity).execute();
                     if (startResult < START_SUCCESS) {
                         // Abort by error result and recycle unused starters.
                         for (int j = i + 1; j < starters.length; j++) {
diff --git a/services/core/java/com/android/server/wm/ActivityStartInterceptor.java b/services/core/java/com/android/server/wm/ActivityStartInterceptor.java
index cc69b5a..effd154a 100644
--- a/services/core/java/com/android/server/wm/ActivityStartInterceptor.java
+++ b/services/core/java/com/android/server/wm/ActivityStartInterceptor.java
@@ -274,7 +274,7 @@
         // ConfirmCredentials intent and unassign it, as otherwise the task will move to
         // front even if ConfirmCredentials is cancelled.
         if (mInTask != null) {
-            mIntent.putExtra(EXTRA_TASK_ID, mInTask.taskId);
+            mIntent.putExtra(EXTRA_TASK_ID, mInTask.mTaskId);
             mInTask = null;
         }
         if (mActivityOptions == null) {
diff --git a/services/core/java/com/android/server/wm/ActivityStarter.java b/services/core/java/com/android/server/wm/ActivityStarter.java
index 54bb5f7..9397893 100644
--- a/services/core/java/com/android/server/wm/ActivityStarter.java
+++ b/services/core/java/com/android/server/wm/ActivityStarter.java
@@ -1557,7 +1557,7 @@
         );
         if (newTask) {
             EventLog.writeEvent(EventLogTags.AM_CREATE_TASK, mStartActivity.mUserId,
-                    mStartActivity.getTaskRecord().taskId);
+                    mStartActivity.getTaskRecord().mTaskId);
         }
         mStartActivity.logStartActivity(
                 EventLogTags.AM_CREATE_ACTIVITY, mStartActivity.getTaskRecord());
@@ -1684,14 +1684,16 @@
                         == (FLAG_ACTIVITY_CLEAR_TOP | FLAG_ACTIVITY_RESET_TASK_IF_NEEDED)
                         && mLaunchMode == LAUNCH_MULTIPLE;
 
-        // If mStartActivity does not have a task associated with it, associate it with the
-        // reused activity's task. Do not do so if we're clearing top and resetting for a
-        // standard launchMode activity.
-        if (mStartActivity.getTaskRecord() == null && !clearTopAndResetStandardLaunchMode) {
-            mStartActivity.setTask(targetTask);
-        }
-
+        boolean clearTaskForReuse = false;
         if (reusedActivity != null) {
+            // If mStartActivity does not have a task associated with it, associate it with the
+            // reused activity's task. Do not do so if we're clearing top and resetting for a
+            // standard launchMode activity.
+            if (mStartActivity.getTaskRecord() == null && !clearTopAndResetStandardLaunchMode) {
+                mStartActivity.setTaskForReuse(reusedActivity.getTaskRecord());
+                clearTaskForReuse = true;
+            }
+
             if (targetTask.intent == null) {
                 // This task was started because of movement of the activity based on
                 // affinity...
@@ -1739,6 +1741,13 @@
 
         complyActivityFlags(targetTask, reusedActivity);
 
+        if (clearTaskForReuse) {
+            // Clear task for re-use so later code to methods
+            // {@link #setTaskFromReuseOrCreateNewTask}, {@link #setTaskFromSourceRecord}, or
+            // {@link #setTaskFromInTask} can parent it to the task.
+            mStartActivity.setTaskForReuse(null);
+        }
+
         if (mAddingToTask) {
             return START_SUCCESS;
         }
diff --git a/services/core/java/com/android/server/wm/ActivityTaskManagerService.java b/services/core/java/com/android/server/wm/ActivityTaskManagerService.java
index 468a13d..9b9dc88 100644
--- a/services/core/java/com/android/server/wm/ActivityTaskManagerService.java
+++ b/services/core/java/com/android/server/wm/ActivityTaskManagerService.java
@@ -63,7 +63,6 @@
 import static android.view.Display.DEFAULT_DISPLAY;
 import static android.view.Display.INVALID_DISPLAY;
 import static android.view.WindowManager.TRANSIT_NONE;
-import static android.view.WindowManager.TRANSIT_TASK_IN_PLACE;
 
 import static com.android.server.am.ActivityManagerService.ANR_TRACE_DIR;
 import static com.android.server.am.ActivityManagerService.MY_PID;
@@ -807,7 +806,7 @@
         mUiHandler = new UiHandler();
         mIntentFirewall = intentFirewall;
         final File systemDir = SystemServiceManager.ensureSystemDir();
-        mAppWarnings = new AppWarnings(this, mUiContext, mH, mUiHandler, systemDir);
+        mAppWarnings = createAppWarnings(mUiContext, mH, mUiHandler, systemDir);
         mCompatModePackages = new CompatModePackages(this, systemDir, mH);
         mPendingIntentController = intentController;
 
@@ -845,6 +844,11 @@
         return supervisor;
     }
 
+    protected AppWarnings createAppWarnings(
+            Context uiContext, Handler handler, Handler uiHandler, File systemDir) {
+        return new AppWarnings(this, uiContext, handler, uiHandler, systemDir);
+    }
+
     public void setWindowManager(WindowManagerService wm) {
         synchronized (mGlobalLock) {
             mWindowManager = wm;
@@ -1613,7 +1617,7 @@
                     // because we don't support returning them across task boundaries. Also, to
                     // keep backwards compatibility we remove the task from recents when finishing
                     // task with root activity.
-                    res = mStackSupervisor.removeTaskByIdLocked(tr.taskId, false /* killProcess */,
+                    res = mStackSupervisor.removeTaskByIdLocked(tr.mTaskId, false /* killProcess */,
                             finishWithRootActivity, "finish-activity");
                     if (!res) {
                         Slog.i(TAG, "Removing task failed to finish activity");
@@ -1813,11 +1817,9 @@
     @Override
     public int getRequestedOrientation(IBinder token) {
         synchronized (mGlobalLock) {
-            ActivityRecord r = ActivityRecord.isInStackLocked(token);
-            if (r == null) {
-                return ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED;
-            }
-            return r.getOrientation();
+            final ActivityRecord r = ActivityRecord.isInStackLocked(token);
+            return (r != null)
+                    ? r.getRequestedOrientation() : ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED;
         }
     }
 
@@ -2230,7 +2232,7 @@
             final TaskRecord tr = mRootActivityContainer.anyTaskForId(id,
                     MATCH_TASK_IN_STACKS_OR_RECENT_TASKS);
             if (tr != null) {
-                return tr.lastTaskDescription;
+                return tr.mTaskDescription;
             }
         }
         return null;
@@ -3029,7 +3031,7 @@
             }
             if (structure != null) {
                 // Pre-fill the task/activity component for all assist data receivers
-                structure.setTaskId(pae.activity.getTaskRecord().taskId);
+                structure.setTaskId(pae.activity.getTaskRecord().mTaskId);
                 structure.setActivityComponent(pae.activity.mActivityComponent);
                 structure.setHomeActivity(pae.isHome);
             }
@@ -3056,7 +3058,7 @@
                 // Caller wants result sent back to them.
                 sendBundle = new Bundle();
                 sendBundle.putInt(ActivityTaskManagerInternal.ASSIST_TASK_ID,
-                        pae.activity.getTaskRecord().taskId);
+                        pae.activity.getTaskRecord().mTaskId);
                 sendBundle.putBinder(ActivityTaskManagerInternal.ASSIST_ACTIVITY_ID,
                         pae.activity.assistToken);
                 sendBundle.putBundle(ASSIST_KEY_DATA, pae.extras);
@@ -3152,11 +3154,11 @@
                     stack.removeTask(task, "addAppTask", REMOVE_TASK_MODE_DESTROYING);
                     return INVALID_TASK_ID;
                 }
-                task.lastTaskDescription.copyFrom(description);
+                task.mTaskDescription.copyFrom(description);
 
                 // TODO: Send the thumbnail to WM to store it.
 
-                return task.taskId;
+                return task.mTaskId;
             }
         } finally {
             Binder.restoreCallingIdentity(callingIdent);
@@ -3318,29 +3320,6 @@
     }
 
     @Override
-    public void startInPlaceAnimationOnFrontMostApplication(Bundle opts) {
-        final SafeActivityOptions safeOptions = SafeActivityOptions.fromBundle(opts);
-        final ActivityOptions activityOptions = safeOptions != null
-                ? safeOptions.getOptions(mStackSupervisor)
-                : null;
-        if (activityOptions == null
-                || activityOptions.getAnimationType() != ActivityOptions.ANIM_CUSTOM_IN_PLACE
-                || activityOptions.getCustomInPlaceResId() == 0) {
-            throw new IllegalArgumentException("Expected in-place ActivityOption " +
-                    "with valid animation");
-        }
-        // Get top display of front most application.
-        final ActivityStack focusedStack = getTopDisplayFocusedStack();
-        if (focusedStack != null) {
-            final DisplayContent dc = focusedStack.getDisplay().mDisplayContent;
-            dc.prepareAppTransition(TRANSIT_TASK_IN_PLACE, false);
-            dc.mAppTransition.overrideInPlaceAppTransition(activityOptions.getPackageName(),
-                    activityOptions.getCustomInPlaceResId());
-            dc.executeAppTransition();
-        }
-    }
-
-    @Override
     public void removeStack(int stackId) {
         enforceCallerIsRecentsOrHasPermission(MANAGE_ACTIVITY_STACKS, "removeStack()");
         synchronized (mGlobalLock) {
@@ -4964,8 +4943,8 @@
                 if (lastTask != task) {
                     lastTask = task;
                     pw.print("TASK "); pw.print(lastTask.affinity);
-                    pw.print(" id="); pw.print(lastTask.taskId);
-                    pw.print(" userId="); pw.println(lastTask.userId);
+                    pw.print(" id="); pw.print(lastTask.mTaskId);
+                    pw.print(" userId="); pw.println(lastTask.mUserId);
                     if (dumpAll) {
                         lastTask.dump(pw, "  ");
                     }
diff --git a/services/core/java/com/android/server/wm/AppTransition.java b/services/core/java/com/android/server/wm/AppTransition.java
index 93c461f..394b475 100644
--- a/services/core/java/com/android/server/wm/AppTransition.java
+++ b/services/core/java/com/android/server/wm/AppTransition.java
@@ -33,7 +33,6 @@
 import static android.view.WindowManager.TRANSIT_SHOW_SINGLE_TASK_DISPLAY;
 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_IN_PLACE;
 import static android.view.WindowManager.TRANSIT_TASK_OPEN;
 import static android.view.WindowManager.TRANSIT_TASK_OPEN_BEHIND;
 import static android.view.WindowManager.TRANSIT_TASK_TO_BACK;
@@ -2257,8 +2256,7 @@
     static boolean isTaskTransit(int transit) {
         return isTaskOpenTransit(transit)
                 || transit == TRANSIT_TASK_CLOSE
-                || transit == TRANSIT_TASK_TO_BACK
-                || transit == TRANSIT_TASK_IN_PLACE;
+                || transit == TRANSIT_TASK_TO_BACK;
     }
 
     private static  boolean isTaskOpenTransit(int transit) {
diff --git a/services/core/java/com/android/server/wm/AppTransitionController.java b/services/core/java/com/android/server/wm/AppTransitionController.java
index 20a871b..894dfd4 100644
--- a/services/core/java/com/android/server/wm/AppTransitionController.java
+++ b/services/core/java/com/android/server/wm/AppTransitionController.java
@@ -31,7 +31,6 @@
 import static android.view.WindowManager.TRANSIT_NONE;
 import static android.view.WindowManager.TRANSIT_SHOW_SINGLE_TASK_DISPLAY;
 import static android.view.WindowManager.TRANSIT_TASK_CLOSE;
-import static android.view.WindowManager.TRANSIT_TASK_IN_PLACE;
 import static android.view.WindowManager.TRANSIT_TASK_OPEN;
 import static android.view.WindowManager.TRANSIT_TASK_TO_BACK;
 import static android.view.WindowManager.TRANSIT_TASK_TO_FRONT;
@@ -179,8 +178,6 @@
         final int layoutRedo;
         mService.mSurfaceAnimationRunner.deferStartingAnimations();
         try {
-            processApplicationsAnimatingInPlace(transit);
-
             handleClosingApps(transit, animLp, voiceInteraction);
             handleOpeningApps(transit, animLp, voiceInteraction);
             handleChangingApps(transit, animLp, voiceInteraction);
@@ -710,19 +707,4 @@
         }
         return topApp;
     }
-
-    private void processApplicationsAnimatingInPlace(int transit) {
-        if (transit == TRANSIT_TASK_IN_PLACE) {
-            // Find the focused window
-            final WindowState win = mDisplayContent.findFocusedWindow();
-            if (win != null) {
-                final AppWindowToken wtoken = win.mAppToken;
-                ProtoLog.v(WM_DEBUG_APP_TRANSITIONS, "Now animating app in place %s", wtoken);
-                wtoken.cancelAnimation();
-                wtoken.applyAnimationLocked(null, transit, false, false);
-                wtoken.updateReportedVisibilityLocked();
-                wtoken.showAllWindowsLocked();
-            }
-        }
-    }
 }
diff --git a/services/core/java/com/android/server/wm/AppWindowToken.java b/services/core/java/com/android/server/wm/AppWindowToken.java
index 2668628..a261341 100644
--- a/services/core/java/com/android/server/wm/AppWindowToken.java
+++ b/services/core/java/com/android/server/wm/AppWindowToken.java
@@ -21,8 +21,15 @@
 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;
@@ -62,6 +69,9 @@
 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;
@@ -84,12 +94,17 @@
 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;
@@ -98,14 +113,13 @@
 import android.os.Build;
 import android.os.Debug;
 import android.os.IBinder;
-import android.os.RemoteException;
 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.IApplicationToken;
 import android.view.InputApplicationHandle;
 import android.view.RemoteAnimationAdapter;
 import android.view.RemoteAnimationDefinition;
@@ -140,8 +154,8 @@
  * Version of WindowToken that is specifically for a particular application (or
  * really activity) that is displaying windows.
  */
-class AppWindowToken extends WindowToken implements WindowManagerService.AppFreezeListener,
-        ConfigurationContainerListener {
+// 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;
 
     /**
@@ -149,17 +163,36 @@
      */
     @VisibleForTesting static final int Z_BOOST_BASE = 800570000;
 
+    final ActivityTaskManagerService mAtmService;
     // Non-null only for application tokens.
-    final IApplicationToken appToken;
+    // 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;
-    final boolean mVoiceInteraction;
+    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
@@ -234,10 +267,12 @@
     boolean mLaunchTaskBehind;
     boolean mEnteringAnimation;
 
-    private boolean mAlwaysFocusable;
-
     boolean mAppStopped;
-    int mRotationAnimationHint;
+    // 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;
@@ -261,9 +296,6 @@
 
     private Task mLastParent;
 
-    // TODO: Remove after unification
-    ActivityRecord mActivityRecord;
-
     /**
      * @see #currentLaunchCanTurnScreenOn()
      */
@@ -327,6 +359,10 @@
     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 =
@@ -341,23 +377,67 @@
                 }
             });
 
-    AppWindowToken(WindowManagerService service, IApplicationToken token,
-            ComponentName activityComponent, boolean voiceInteraction, DisplayContent dc,
-            long inputDispatchingTimeoutNanos, boolean fullscreen, boolean showForAllUsers,
-            int targetSdk, int orientation, int rotationAnimationHint,
-            boolean launchTaskBehind, boolean alwaysFocusable,
-            ActivityRecord activityRecord) {
-        this(service, token, activityComponent, voiceInteraction, dc, fullscreen);
-        // TODO: remove after unification
-        mActivityRecord = activityRecord;
-        mActivityRecord.registerConfigurationChangeListener(this);
-        mInputDispatchingTimeoutNanos = inputDispatchingTimeoutNanos;
-        mShowForAllUsers = showForAllUsers;
-        mTargetSdk = targetSdk;
-        mOrientation = orientation;
-        mLaunchTaskBehind = launchTaskBehind;
-        mAlwaysFocusable = alwaysFocusable;
-        mRotationAnimationHint = rotationAnimationHint;
+    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);
@@ -365,20 +445,19 @@
 
         ColorDisplayService.ColorDisplayServiceInternal cds = LocalServices.getService(
                 ColorDisplayService.ColorDisplayServiceInternal.class);
-        cds.attachColorTransformController(activityRecord.packageName, activityRecord.mUserId,
+        cds.attachColorTransformController(packageName, mUserId,
                 new WeakReference<>(mColorTransformController));
     }
 
-    AppWindowToken(WindowManagerService service, IApplicationToken token,
-            ComponentName activityComponent, boolean voiceInteraction, DisplayContent dc,
-            boolean fillsParent) {
-        super(service, token != null ? token.asBinder() : null, TYPE_APPLICATION, true, dc,
-                false /* ownerCanManageAppTokens */);
-        appToken = token;
-        mActivityComponent = activityComponent;
+    void onAttachToTask(boolean voiceInteraction, DisplayContent dc,
+            long inputDispatchingTimeoutNanos) {
+        mInputDispatchingTimeoutNanos = inputDispatchingTimeoutNanos;
         mVoiceInteraction = voiceInteraction;
-        mOccludesParent = fillsParent;
-        mInputApplicationHandle = new InputApplicationHandle(appToken.asBinder());
+        onDisplayChanged(dc);
+
+        // Application tokens start out hidden.
+        setHidden(true);
+        hiddenRequested = true;
     }
 
     void onFirstWindowDrawn(WindowState win, WindowStateAnimator winAnimator) {
@@ -433,43 +512,33 @@
         if (DEBUG_VISIBILITY) Slog.v(TAG, "VIS " + this + ": interesting="
                 + numInteresting + " visible=" + numVisible);
         if (nowDrawn != reportedDrawn) {
-            if (mActivityRecord != null) {
-                mActivityRecord.onWindowsDrawn(nowDrawn, SystemClock.uptimeMillis());
-            }
+            onWindowsDrawn(nowDrawn, SystemClock.uptimeMillis());
             reportedDrawn = nowDrawn;
         }
         if (nowVisible != reportedVisible) {
             if (DEBUG_VISIBILITY) Slog.v(TAG,
                     "Visibility changed in " + this + ": vis=" + nowVisible);
             reportedVisible = nowVisible;
-            if (mActivityRecord != null) {
-                if (nowVisible) {
-                    onWindowsVisible();
-                } else {
-                    onWindowsGone();
-                }
+            if (nowVisible) {
+                onWindowsVisible();
+            } else {
+                onWindowsGone();
             }
         }
     }
 
-    private void onWindowsGone() {
-        if (mActivityRecord == null) {
-            return;
-        }
-        if (DEBUG_VISIBILITY) {
-            Slog.v(TAG_WM, "Reporting gone in " + mActivityRecord.appToken);
-        }
-        mActivityRecord.onWindowsGone();
+    // Mostly implemented in ActivityRecord.
+    void onWindowsDrawn(boolean drawn, long timestamp) {
     }
 
-    private void onWindowsVisible() {
-        if (mActivityRecord == null) {
-            return;
-        }
-        if (DEBUG_VISIBILITY) {
-            Slog.v(TAG_WM, "Reporting visible in " + mActivityRecord.appToken);
-        }
-        mActivityRecord.onWindowsVisible();
+    // 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() {
@@ -604,8 +673,6 @@
                     }
                 }
             }
-            // Changes in opening apps and closing apps may cause orientation change.
-            reportDescendantOrientationChangeIfNeeded();
             return;
         }
 
@@ -762,29 +829,27 @@
                 }
                 SurfaceControl.closeTransaction();
             }
-
-            // Visibility changes may cause orientation request change.
-            reportDescendantOrientationChangeIfNeeded();
         }
 
         return delayed;
     }
 
-    private void reportDescendantOrientationChangeIfNeeded() {
+    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 (mActivityRecord.getRequestedConfigurationOrientation() == getConfiguration().orientation
-                || getOrientationIgnoreVisibility() == SCREEN_ORIENTATION_UNSET) {
+        if (getRequestedOrientation() == SCREEN_ORIENTATION_UNSET) {
             return;
         }
 
-        final IBinder freezeToken =
-                mActivityRecord.mayFreezeScreenLocked(mActivityRecord.app)
-                        ? mActivityRecord.appToken : null;
-        onDescendantOrientationChanged(freezeToken, mActivityRecord);
+        final IBinder freezeToken = mayFreezeScreenLocked() ? appToken : null;
+        onDescendantOrientationChanged(freezeToken, this);
     }
 
     /**
@@ -834,10 +899,16 @@
         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 = mActivityRecord != null
-                    ? (mActivityRecord.app != null ? mActivityRecord.app.getPid() : 0) : 0;
+            final int pid = getPid();
             final AppWindowToken topFocusedAppOfMyProcess =
                     mWmService.mRoot.mTopFocusedAppByProcess.get(pid);
             if (topFocusedAppOfMyProcess != null && topFocusedAppOfMyProcess != this) {
@@ -846,7 +917,12 @@
                 return false;
             }
         }
-        return getWindowConfiguration().canReceiveKeys() || mAlwaysFocusable;
+        return getWindowConfiguration().canReceiveKeys() || isAlwaysFocusable();
+    }
+
+    // Mostly implemented in ActivityRecord...
+    int getPid() {
+        return 0;
     }
 
     @Override
@@ -859,9 +935,6 @@
     @Override
     void removeImmediately() {
         onRemovedFromDisplay();
-        if (mActivityRecord != null) {
-            mActivityRecord.unregisterConfigurationChangeListener(this);
-        }
         super.removeImmediately();
     }
 
@@ -1065,7 +1138,9 @@
             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.
-                getDisplayContent().mClosingApps.remove(this);
+                if (getDisplayContent() != null) {
+                    getDisplayContent().mClosingApps.remove(this);
+                }
             } else if (mLastParent != null && mLastParent.mStack != null) {
                 task.mStack.mExitingAppTokens.remove(this);
             }
@@ -1655,27 +1730,18 @@
     }
 
     /** Returns the app's preferred orientation regardless of its currently visibility state. */
-    int getOrientationIgnoreVisibility() {
+    int getRequestedOrientation() {
         return mOrientation;
     }
 
     /** @return {@code true} if the compatibility bounds is taking effect. */
-    boolean inSizeCompatMode() {
+    boolean hasSizeCompatBounds() {
         return mSizeCompatBounds != null;
     }
 
     @Override
     float getSizeCompatScale() {
-        return inSizeCompatMode() ? mSizeCompatScale : super.getSizeCompatScale();
-    }
-
-    /**
-     * @return Non-empty bounds if the activity has override bounds.
-     * @see ActivityRecord#resolveOverrideConfiguration(Configuration)
-     */
-    Rect getResolvedOverrideBounds() {
-        // Get bounds from resolved override configuration because it is computed with orientation.
-        return getResolvedOverrideConfiguration().windowConfiguration.getBounds();
+        return hasSizeCompatBounds() ? mSizeCompatScale : super.getSizeCompatScale();
     }
 
     @Override
@@ -1708,7 +1774,7 @@
 
         final int winMode = getWindowingMode();
 
-        if (prevWinMode == winMode) {
+        if (prevWinMode == winMode || mDisplayContent == null) {
             return;
         }
 
@@ -1951,8 +2017,9 @@
         }
     }
 
+    // Mostly implemented in ActivityRecord...
     boolean keyDispatchingTimedOut(String reason, int windowPid) {
-        return mActivityRecord != null && mActivityRecord.keyDispatchingTimedOut(reason, windowPid);
+        return false;
     }
 
     /**
@@ -2019,9 +2086,7 @@
                     }
                 }
             } else if (w.isDrawnLw()) {
-                if (mActivityRecord != null) {
-                    mActivityRecord.onStartingWindowDrawn(SystemClock.uptimeMillis());
-                }
+                onStartingWindowDrawn(SystemClock.uptimeMillis());
                 startingDisplayed = true;
             }
         }
@@ -2029,6 +2094,14 @@
         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) {
@@ -2413,6 +2486,66 @@
         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();
@@ -2797,7 +2930,7 @@
             layer += Z_BOOST_BASE;
         }
         if (!mNeedsAnimationBoundsLayer) {
-            leash.setLayer(layer);
+            t.setLayer(leash, layer);
         }
 
         final DisplayContent dc = getDisplayContent();
@@ -2890,7 +3023,21 @@
         getDisplayContent().mAppTransition.notifyAppTransitionFinishedLocked(token);
         scheduleAnimation();
 
-        mActivityRecord.onAnimationFinished();
+        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);
     }
 
@@ -2957,10 +3104,13 @@
     }
 
     boolean isWaitingForTransitionStart() {
-        return getDisplayContent().mAppTransition.isTransitionSet()
-                && (getDisplayContent().mOpeningApps.contains(this)
-                    || getDisplayContent().mClosingApps.contains(this)
-                    || getDisplayContent().mChangingApps.contains(this));
+        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() {
@@ -3204,27 +3354,17 @@
     }
 
     void writeNameToProto(ProtoOutputStream proto, long fieldId) {
-        if (appToken == null) {
-            return;
-        }
-        try {
+        if (appToken != null) {
             proto.write(fieldId, appToken.getName());
-        } catch (RemoteException e) {
-            // This shouldn't happen, but in this case fall back to outputting nothing
-            Slog.e(TAG, e.toString());
         }
     }
 
-    @Override
-    public String toString() {
-        if (stringName == null) {
-            StringBuilder sb = new StringBuilder();
-            sb.append("AppWindowToken{");
-            sb.append(Integer.toHexString(System.identityHashCode(this)));
-            sb.append(" token="); sb.append(token); sb.append('}');
-            stringName = sb.toString();
-        }
-        return stringName + ((mIsExiting) ? " mIsExiting=" : "");
+    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() {
diff --git a/services/core/java/com/android/server/wm/CircularDisplayMask.java b/services/core/java/com/android/server/wm/CircularDisplayMask.java
index c1ca816..b73b481 100644
--- a/services/core/java/com/android/server/wm/CircularDisplayMask.java
+++ b/services/core/java/com/android/server/wm/CircularDisplayMask.java
@@ -56,7 +56,7 @@
     private int mMaskThickness;
 
     CircularDisplayMask(Supplier<Surface> surfaceFactory, DisplayContent dc, int zOrder,
-            int screenOffset, int maskThickness) {
+            int screenOffset, int maskThickness, SurfaceControl.Transaction t) {
         final Display display = dc.getDisplay();
         mSurface = surfaceFactory.get();
         mScreenSize = new Point();
@@ -75,10 +75,10 @@
                     .setFormat(PixelFormat.TRANSLUCENT)
                     .build();
 
-            ctrl.setLayerStack(display.getLayerStack());
-            ctrl.setLayer(zOrder);
-            ctrl.setPosition(0, 0);
-            ctrl.show();
+            t.setLayerStack(ctrl, display.getLayerStack());
+            t.setLayer(ctrl, zOrder);
+            t.setPosition(ctrl, 0, 0);
+            t.show(ctrl);
             mSurface.copyFrom(ctrl);
         } catch (OutOfResourcesException e) {
         }
@@ -91,7 +91,7 @@
         mMaskThickness = maskThickness;
     }
 
-    private void drawIfNeeded() {
+    private void drawIfNeeded(SurfaceControl.Transaction t) {
         if (!mDrawNeeded || !mVisible || mDimensionsUnequal) {
             return;
         }
@@ -108,45 +108,46 @@
             return;
         }
         switch (mRotation) {
-        case Surface.ROTATION_0:
-        case Surface.ROTATION_90:
-            // chin bottom or right
-            mSurfaceControl.setPosition(0, 0);
-            break;
-        case Surface.ROTATION_180:
-            // chin top
-            mSurfaceControl.setPosition(0, -mScreenOffset);
-            break;
-        case Surface.ROTATION_270:
-            // chin left
-            mSurfaceControl.setPosition(-mScreenOffset, 0);
-            break;
+            case Surface.ROTATION_0:
+            case Surface.ROTATION_90:
+                // chin bottom or right
+                t.setPosition(mSurfaceControl, 0, 0);
+                break;
+            case Surface.ROTATION_180:
+                // chin top
+                t.setPosition(mSurfaceControl, 0, -mScreenOffset);
+                break;
+            case Surface.ROTATION_270:
+                // chin left
+                t.setPosition(mSurfaceControl, -mScreenOffset, 0);
+                break;
         }
 
         int circleRadius = mScreenSize.x / 2;
         c.drawColor(Color.BLACK);
 
-        // The radius is reduced by mMaskThickness to provide an anti aliasing effect on the display edges.
+        // The radius is reduced by mMaskThickness to provide an anti aliasing effect on the
+        // display edges.
         c.drawCircle(circleRadius, circleRadius, circleRadius - mMaskThickness, mPaint);
         mSurface.unlockCanvasAndPost(c);
     }
 
     // Note: caller responsible for being inside
     // Surface.openTransaction() / closeTransaction()
-    public void setVisibility(boolean on) {
+    public void setVisibility(boolean on, SurfaceControl.Transaction t) {
         if (mSurfaceControl == null) {
             return;
         }
         mVisible = on;
-        drawIfNeeded();
+        drawIfNeeded(t);
         if (on) {
-            mSurfaceControl.show();
+            t.show(mSurfaceControl);
         } else {
-            mSurfaceControl.hide();
+            t.hide(mSurfaceControl);
         }
     }
 
-    void positionSurface(int dw, int dh, int rotation) {
+    void positionSurface(int dw, int dh, int rotation, SurfaceControl.Transaction t) {
         if (mLastDW == dw && mLastDH == dh && mRotation == rotation) {
             return;
         }
@@ -154,7 +155,7 @@
         mLastDH = dh;
         mDrawNeeded = true;
         mRotation = rotation;
-        drawIfNeeded();
+        drawIfNeeded(t);
     }
 
 }
diff --git a/services/core/java/com/android/server/wm/ConfigurationContainer.java b/services/core/java/com/android/server/wm/ConfigurationContainer.java
index 3886ae1..8afbbdf 100644
--- a/services/core/java/com/android/server/wm/ConfigurationContainer.java
+++ b/services/core/java/com/android/server/wm/ConfigurationContainer.java
@@ -90,7 +90,8 @@
     private ArrayList<ConfigurationContainerListener> mChangeListeners = new ArrayList<>();
 
     // TODO: Can't have ag/2592611 soon enough!
-    private final Configuration mTmpConfig = new Configuration();
+    private final Configuration mRequestsTmpConfig = new Configuration();
+    private final Configuration mResolvedTmpConfig = new Configuration();
 
     // Used for setting bounds
     private final Rect mTmpRect = new Rect();
@@ -121,12 +122,19 @@
      * @see #mFullConfiguration
      */
     public void onConfigurationChanged(Configuration newParentConfig) {
-        mTmpConfig.setTo(mResolvedOverrideConfiguration);
+        onConfigurationChanged(newParentConfig, true /*forwardToChildren*/);
+    }
+
+    // TODO: Consolidate with onConfigurationChanged() method above once unification is done. This
+    // is only currently need during the process of unification where we don't want configuration
+    // forwarded to a child from both parents.
+    public void onConfigurationChanged(Configuration newParentConfig, boolean forwardToChildren) {
+        mResolvedTmpConfig.setTo(mResolvedOverrideConfiguration);
         resolveOverrideConfiguration(newParentConfig);
         mFullConfiguration.setTo(newParentConfig);
         mLastOverrideConfigurationChanges =
                 mFullConfiguration.updateFrom(mResolvedOverrideConfiguration);
-        if (!mTmpConfig.equals(mResolvedOverrideConfiguration)) {
+        if (!mResolvedTmpConfig.equals(mResolvedOverrideConfiguration)) {
             onMergedOverrideConfigurationChanged();
             // This depends on the assumption that change-listeners don't do
             // their own override resolution. This way, dependent hierarchies
@@ -139,9 +147,11 @@
                         mResolvedOverrideConfiguration);
             }
         }
-        for (int i = getChildCount() - 1; i >= 0; --i) {
-            final ConfigurationContainer child = getChildAt(i);
-            child.onConfigurationChanged(mFullConfiguration);
+        if (forwardToChildren) {
+            for (int i = getChildCount() - 1; i >= 0; --i) {
+                final ConfigurationContainer child = getChildAt(i);
+                child.onConfigurationChanged(mFullConfiguration);
+            }
         }
     }
 
@@ -262,6 +272,11 @@
         out.set(bounds.left, bounds.top);
     }
 
+    Rect getResolvedOverrideBounds() {
+        mReturnBounds.set(getResolvedOverrideConfiguration().windowConfiguration.getBounds());
+        return mReturnBounds;
+    }
+
     /**
      * Returns the bounds requested on this container. These may not be the actual bounds the
      * container ends up with due to policy constraints. The {@link Rect} handed back is
@@ -306,9 +321,9 @@
         }
 
 
-        mTmpConfig.setTo(getRequestedOverrideConfiguration());
-        mTmpConfig.windowConfiguration.setBounds(bounds);
-        onRequestedOverrideConfigurationChanged(mTmpConfig);
+        mRequestsTmpConfig.setTo(getRequestedOverrideConfiguration());
+        mRequestsTmpConfig.windowConfiguration.setBounds(bounds);
+        onRequestedOverrideConfigurationChanged(mRequestsTmpConfig);
 
         return boundsChange;
     }
@@ -360,9 +375,9 @@
 
     /** Sets the requested windowing mode override for the configuration container. */
     public void setWindowingMode(/*@WindowConfiguration.WindowingMode*/ int windowingMode) {
-        mTmpConfig.setTo(getRequestedOverrideConfiguration());
-        mTmpConfig.windowConfiguration.setWindowingMode(windowingMode);
-        onRequestedOverrideConfigurationChanged(mTmpConfig);
+        mRequestsTmpConfig.setTo(getRequestedOverrideConfiguration());
+        mRequestsTmpConfig.windowConfiguration.setWindowingMode(windowingMode);
+        onRequestedOverrideConfigurationChanged(mRequestsTmpConfig);
     }
 
     /** Sets the always on top flag for this configuration container.
@@ -372,16 +387,16 @@
      *  - {@Link ActivityDisplay#positionChildAtTop(ActivityStack)};
      * */
     public void setAlwaysOnTop(boolean alwaysOnTop) {
-        mTmpConfig.setTo(getRequestedOverrideConfiguration());
-        mTmpConfig.windowConfiguration.setAlwaysOnTop(alwaysOnTop);
-        onRequestedOverrideConfigurationChanged(mTmpConfig);
+        mRequestsTmpConfig.setTo(getRequestedOverrideConfiguration());
+        mRequestsTmpConfig.windowConfiguration.setAlwaysOnTop(alwaysOnTop);
+        onRequestedOverrideConfigurationChanged(mRequestsTmpConfig);
     }
 
     /** Sets the windowing mode for the configuration container. */
     void setDisplayWindowingMode(int windowingMode) {
-        mTmpConfig.setTo(getRequestedOverrideConfiguration());
-        mTmpConfig.windowConfiguration.setDisplayWindowingMode(windowingMode);
-        onRequestedOverrideConfigurationChanged(mTmpConfig);
+        mRequestsTmpConfig.setTo(getRequestedOverrideConfiguration());
+        mRequestsTmpConfig.windowConfiguration.setDisplayWindowingMode(windowingMode);
+        onRequestedOverrideConfigurationChanged(mRequestsTmpConfig);
     }
 
     /**
@@ -451,9 +466,9 @@
             throw new IllegalStateException("Can't change activity type once set: " + this
                     + " activityType=" + activityTypeToString(activityType));
         }
-        mTmpConfig.setTo(getRequestedOverrideConfiguration());
-        mTmpConfig.windowConfiguration.setActivityType(activityType);
-        onRequestedOverrideConfigurationChanged(mTmpConfig);
+        mRequestsTmpConfig.setTo(getRequestedOverrideConfiguration());
+        mRequestsTmpConfig.windowConfiguration.setActivityType(activityType);
+        onRequestedOverrideConfigurationChanged(mRequestsTmpConfig);
     }
 
     public boolean isActivityTypeHome() {
diff --git a/services/core/java/com/android/server/wm/DisplayContent.java b/services/core/java/com/android/server/wm/DisplayContent.java
index 6fafa9f..4c3611e 100644
--- a/services/core/java/com/android/server/wm/DisplayContent.java
+++ b/services/core/java/com/android/server/wm/DisplayContent.java
@@ -59,11 +59,10 @@
 import static android.view.WindowManager.LayoutParams.NEEDS_MENU_SET_TRUE;
 import static android.view.WindowManager.LayoutParams.NEEDS_MENU_UNSET;
 import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_KEYGUARD;
-import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION;
 import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_STARTING;
+import static android.view.WindowManager.LayoutParams.TYPE_BASE_APPLICATION;
 import static android.view.WindowManager.LayoutParams.TYPE_BOOT_PROGRESS;
 import static android.view.WindowManager.LayoutParams.TYPE_DOCK_DIVIDER;
-import static android.view.WindowManager.LayoutParams.TYPE_DRAWN_APPLICATION;
 import static android.view.WindowManager.LayoutParams.TYPE_DREAM;
 import static android.view.WindowManager.LayoutParams.TYPE_INPUT_METHOD;
 import static android.view.WindowManager.LayoutParams.TYPE_INPUT_METHOD_DIALOG;
@@ -133,7 +132,6 @@
 import static com.android.server.wm.WindowState.EXCLUSION_LEFT;
 import static com.android.server.wm.WindowState.EXCLUSION_RIGHT;
 import static com.android.server.wm.WindowState.RESIZE_HANDLE_WIDTH_IN_DP;
-import static com.android.server.wm.WindowStateAnimator.DRAW_PENDING;
 import static com.android.server.wm.WindowStateAnimator.READY_TO_SHOW;
 import static com.android.server.wm.utils.RegionUtils.forEachRectReverse;
 import static com.android.server.wm.utils.RegionUtils.rectListToRegion;
@@ -169,6 +167,7 @@
 import android.util.ArraySet;
 import android.util.DisplayMetrics;
 import android.util.Slog;
+import android.util.SparseBooleanArray;
 import android.util.proto.ProtoOutputStream;
 import android.view.Display;
 import android.view.DisplayCutout;
@@ -221,7 +220,7 @@
  * particular Display.
  */
 class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowContainer>
-        implements WindowManagerPolicy.DisplayContentInfo {
+        implements WindowManagerPolicy.DisplayContentInfo, ConfigurationContainerListener {
     private static final String TAG = TAG_WITH_CLASS_NAME ? "DisplayContent" : TAG_WM;
 
     /** The default scaling mode that scales content automatically. */
@@ -240,7 +239,7 @@
     private final int mDisplayId;
 
     // TODO: Remove once unification is complete.
-    ActivityDisplay mAcitvityDisplay;
+    ActivityDisplay mActivityDisplay;
 
     /** The containers below are the only child containers the display can have. */
     // Contains all window containers that are related to apps (Activities)
@@ -332,7 +331,7 @@
 
     /**
      * For default display it contains real metrics, empty for others.
-     * @see WindowManagerService#createWatermarkInTransaction()
+     * @see WindowManagerService#createWatermark()
      */
     final DisplayMetrics mRealDisplayMetrics = new DisplayMetrics();
 
@@ -439,11 +438,6 @@
     /** A collection of windows that provide tap exclude regions inside of them. */
     final ArraySet<WindowState> mTapExcludeProvidingWindows = new ArraySet<>();
 
-    private boolean mHaveBootMsg = false;
-    private boolean mHaveApp = false;
-    private boolean mHaveWallpaper = false;
-    private boolean mHaveKeyguard = true;
-
     private final LinkedList<AppWindowToken> mTmpUpdateAllDrawn = new LinkedList();
 
     private final TaskForResizePointSearchResult mTmpTaskForResizePointSearchResult =
@@ -857,7 +851,7 @@
     DisplayContent(Display display, WindowManagerService service,
             ActivityDisplay activityDisplay) {
         super(service);
-        mAcitvityDisplay = activityDisplay;
+        mActivityDisplay = activityDisplay;
         if (service.mRoot.getDisplayContent(display.getDisplayId()) != null) {
             throw new IllegalArgumentException("Display with ID=" + display.getDisplayId()
                     + " already exists=" + service.mRoot.getDisplayContent(display.getDisplayId())
@@ -1141,10 +1135,12 @@
      * values from being replaced by the initializing {@link #ActivityDisplay}.
      */
     void initializeDisplayOverrideConfiguration() {
-        if (mAcitvityDisplay != null) {
-            mAcitvityDisplay.getRequestedOverrideConfiguration()
-                    .updateFrom(getRequestedOverrideConfiguration());
+        if (mActivityDisplay == null) {
+            return;
         }
+        mActivityDisplay.onRequestedOverrideConfigurationChanged(
+                getResolvedOverrideConfiguration());
+        mActivityDisplay.registerConfigurationChangeListener(this);
     }
 
     void reconfigureDisplayLocked() {
@@ -1170,10 +1166,10 @@
     }
 
     void sendNewConfiguration() {
-        if (!isReady() || mAcitvityDisplay == null) {
+        if (!isReady() || mActivityDisplay == null) {
             return;
         }
-        final boolean configUpdated = mAcitvityDisplay.updateDisplayOverrideConfigurationLocked();
+        final boolean configUpdated = mActivityDisplay.updateDisplayOverrideConfigurationLocked();
         if (configUpdated) {
             return;
         }
@@ -1204,7 +1200,7 @@
 
         if (handled && requestingContainer instanceof ActivityRecord) {
             final ActivityRecord activityRecord = (ActivityRecord) requestingContainer;
-            final boolean kept = mAcitvityDisplay.updateDisplayOverrideConfigurationLocked(
+            final boolean kept = mActivityDisplay.updateDisplayOverrideConfigurationLocked(
                     config, activityRecord, false /* deferResume */, null /* result */);
             activityRecord.frozenBeforeDestroy = true;
             if (!kept) {
@@ -1213,7 +1209,7 @@
         } else {
             // We have a new configuration to push so we need to update ATMS for now.
             // TODO: Clean up display configuration push between ATMS and WMS after unification.
-            mAcitvityDisplay.updateDisplayOverrideConfigurationLocked(
+            mActivityDisplay.updateDisplayOverrideConfigurationLocked(
                     config, null /* starting */, false /* deferResume */, null);
         }
         return handled;
@@ -2378,6 +2374,9 @@
     void removeImmediately() {
         mRemovingDisplay = true;
         try {
+            if (mActivityDisplay != null) {
+                mActivityDisplay.unregisterConfigurationChangeListener(this);
+            }
             if (mParentWindow != null) {
                 mParentWindow.removeEmbeddedDisplayContent(this);
             }
@@ -2640,13 +2639,13 @@
             mFocusedApp.writeNameToProto(proto, FOCUSED_APP);
         }
         for (int i = mOpeningApps.size() - 1; i >= 0; i--) {
-            mOpeningApps.valueAt(i).mActivityRecord.writeIdentifierToProto(proto, OPENING_APPS);
+            mOpeningApps.valueAt(i).writeIdentifierToProto(proto, OPENING_APPS);
         }
         for (int i = mClosingApps.size() - 1; i >= 0; i--) {
-            mClosingApps.valueAt(i).mActivityRecord.writeIdentifierToProto(proto, CLOSING_APPS);
+            mClosingApps.valueAt(i).writeIdentifierToProto(proto, CLOSING_APPS);
         }
         for (int i = mChangingApps.size() - 1; i >= 0; i--) {
-            mChangingApps.valueAt(i).mActivityRecord.writeIdentifierToProto(proto, CHANGING_APPS);
+            mChangingApps.valueAt(i).writeIdentifierToProto(proto, CHANGING_APPS);
         }
         proto.end(token);
     }
@@ -3350,34 +3349,38 @@
         }, true /* traverseTopToBottom */);
     }
 
-    boolean checkWaitingForWindows() {
+    /** @return {@code true} if there is window to wait before enabling the screen. */
+    boolean shouldWaitForSystemDecorWindowsOnBoot() {
+        if (!isDefaultDisplay && !supportsSystemDecorations()) {
+            // Nothing to wait because the secondary display doesn't support system decorations,
+            // there is no wallpaper, keyguard (status bar) or application (home) window to show
+            // during booting.
+            return false;
+        }
 
-        mHaveBootMsg = false;
-        mHaveApp = false;
-        mHaveWallpaper = false;
-        mHaveKeyguard = true;
+        final SparseBooleanArray drawnWindowTypes = new SparseBooleanArray();
+        // Presuppose keyguard is drawn because if its window isn't attached, we don't know if it
+        // wants to be shown or hidden, then it should not delay enabling the screen.
+        drawnWindowTypes.put(TYPE_STATUS_BAR, true);
 
-        final WindowState visibleWindow = getWindow(w -> {
-            if (w.isVisibleLw() && !w.mObscured && !w.isDrawnLw()) {
+        final WindowState visibleNotDrawnWindow = getWindow(w -> {
+            if (w.mViewVisibility == View.VISIBLE && !w.mObscured && !w.isDrawnLw()) {
                 return true;
             }
             if (w.isDrawnLw()) {
-                if (w.mAttrs.type == TYPE_BOOT_PROGRESS) {
-                    mHaveBootMsg = true;
-                } else if (w.mAttrs.type == TYPE_APPLICATION
-                        || w.mAttrs.type == TYPE_DRAWN_APPLICATION) {
-                    mHaveApp = true;
-                } else if (w.mAttrs.type == TYPE_WALLPAPER) {
-                    mHaveWallpaper = true;
-                } else if (w.mAttrs.type == TYPE_STATUS_BAR) {
-                    mHaveKeyguard = mWmService.mPolicy.isKeyguardDrawnLw();
+                final int type = w.mAttrs.type;
+                if (type == TYPE_BOOT_PROGRESS || type == TYPE_BASE_APPLICATION
+                        || type == TYPE_WALLPAPER) {
+                    drawnWindowTypes.put(type, true);
+                } else if (type == TYPE_STATUS_BAR) {
+                    drawnWindowTypes.put(TYPE_STATUS_BAR, mWmService.mPolicy.isKeyguardDrawnLw());
                 }
             }
             return false;
         });
 
-        if (visibleWindow != null) {
-            // We have a visible window.
+        if (visibleNotDrawnWindow != null) {
+            // Wait for the visible window to be drawn.
             return true;
         }
 
@@ -3389,22 +3392,27 @@
                         com.android.internal.R.bool.config_checkWallpaperAtBoot)
                 && !mWmService.mOnlyCore;
 
+        final boolean haveBootMsg = drawnWindowTypes.get(TYPE_BOOT_PROGRESS);
+        final boolean haveApp = drawnWindowTypes.get(TYPE_BASE_APPLICATION);
+        final boolean haveWallpaper = drawnWindowTypes.get(TYPE_WALLPAPER);
+        final boolean haveKeyguard = drawnWindowTypes.get(TYPE_STATUS_BAR);
+
         ProtoLog.i(WM_DEBUG_SCREEN_ON,
-                        "******** booted=%b msg=%b haveBoot=%b haveApp=%b haveWall=%b "
-                                + "wallEnabled=%b haveKeyguard=%b",
-                        mWmService.mSystemBooted, mWmService.mShowingBootMessages, mHaveBootMsg,
-                        mHaveApp, mHaveWallpaper, wallpaperEnabled, mHaveKeyguard);
+                "******** booted=%b msg=%b haveBoot=%b haveApp=%b haveWall=%b "
+                        + "wallEnabled=%b haveKeyguard=%b",
+                mWmService.mSystemBooted, mWmService.mShowingBootMessages, haveBootMsg,
+                haveApp, haveWallpaper, wallpaperEnabled, haveKeyguard);
 
         // If we are turning on the screen to show the boot message, don't do it until the boot
         // message is actually displayed.
-        if (!mWmService.mSystemBooted && !mHaveBootMsg) {
+        if (!mWmService.mSystemBooted && !haveBootMsg) {
             return true;
         }
 
         // If we are turning on the screen after the boot is completed normally, don't do so until
         // we have the application and wallpaper.
         if (mWmService.mSystemBooted
-                && ((!mHaveApp && !mHaveKeyguard) || (wallpaperEnabled && !mHaveWallpaper))) {
+                && ((!haveApp && !haveKeyguard) || (wallpaperEnabled && !haveWallpaper))) {
             return true;
         }
 
@@ -3510,19 +3518,6 @@
         mWmService.mWindowPlacerLocked.performSurfacePlacement();
     }
 
-    void waitForAllWindowsDrawn() {
-        final WindowManagerPolicy policy = mWmService.mPolicy;
-        forAllWindows(w -> {
-            final boolean keyguard = policy.isKeyguardHostWindow(w.mAttrs);
-            if (w.isVisibleLw() && (w.mAppToken != null || keyguard)) {
-                w.mWinAnimator.mDrawState = DRAW_PENDING;
-                // Force add to mResizingWindows.
-                w.resetLastContentInsets();
-                mWmService.mWaitingForDrawn.add(w);
-            }
-        }, true /* traverseTopToBottom */);
-    }
-
     // TODO: Super crazy long method that should be broken down...
     void applySurfaceChangesTransaction(boolean recoveringMemory) {
         final WindowSurfacePlacer surfacePlacer = mWmService.mWindowPlacerLocked;
@@ -5157,7 +5152,7 @@
         // Let surface flinger to set the display ID of this input window handle because we don't
         // know which display the parent surface control is on.
         final InputWindowHandle portalWindowHandle = new InputWindowHandle(
-                null /* inputApplicationHandle */, null /* clientWindow */, INVALID_DISPLAY);
+                null /* inputApplicationHandle */, INVALID_DISPLAY);
         portalWindowHandle.name = name;
         portalWindowHandle.token = new Binder();
         portalWindowHandle.layoutParamsFlags =
diff --git a/services/core/java/com/android/server/wm/DisplayPolicy.java b/services/core/java/com/android/server/wm/DisplayPolicy.java
index 7be4dbd..150ae79 100644
--- a/services/core/java/com/android/server/wm/DisplayPolicy.java
+++ b/services/core/java/com/android/server/wm/DisplayPolicy.java
@@ -16,13 +16,12 @@
 
 package com.android.server.wm;
 
-import static android.app.WindowConfiguration.ACTIVITY_TYPE_HOME;
 import static android.app.WindowConfiguration.ACTIVITY_TYPE_STANDARD;
+import static android.app.WindowConfiguration.ACTIVITY_TYPE_UNDEFINED;
 import static android.app.WindowConfiguration.WINDOWING_MODE_FREEFORM;
 import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN;
 import static android.app.WindowConfiguration.WINDOWING_MODE_SPLIT_SCREEN_PRIMARY;
 import static android.app.WindowConfiguration.WINDOWING_MODE_SPLIT_SCREEN_SECONDARY;
-import static android.app.WindowConfiguration.WINDOWING_MODE_UNDEFINED;
 import static android.content.res.Configuration.UI_MODE_TYPE_CAR;
 import static android.content.res.Configuration.UI_MODE_TYPE_MASK;
 import static android.view.Display.TYPE_BUILT_IN;
@@ -3130,9 +3129,10 @@
         final int dockedVisibility = updateLightStatusBarLw(0 /* vis */,
                 mTopDockedOpaqueWindowState, mTopDockedOpaqueOrDimmingWindowState);
         mService.getStackBounds(
-                WINDOWING_MODE_UNDEFINED, ACTIVITY_TYPE_HOME, mNonDockedStackBounds);
-        mService.getStackBounds(
                 WINDOWING_MODE_SPLIT_SCREEN_PRIMARY, ACTIVITY_TYPE_STANDARD, mDockedStackBounds);
+        mService.getStackBounds(mDockedStackBounds.isEmpty()
+                        ? WINDOWING_MODE_FULLSCREEN : WINDOWING_MODE_SPLIT_SCREEN_SECONDARY,
+                ACTIVITY_TYPE_UNDEFINED, mNonDockedStackBounds);
         final Pair<Integer, Boolean> result =
                 updateSystemBarsLw(win, mLastSystemUiFlags, tmpVisibility);
         final int visibility = result.first;
diff --git a/services/core/java/com/android/server/wm/DockedStackDividerController.java b/services/core/java/com/android/server/wm/DockedStackDividerController.java
index ae3b5f2..d3e42901 100644
--- a/services/core/java/com/android/server/wm/DockedStackDividerController.java
+++ b/services/core/java/com/android/server/wm/DockedStackDividerController.java
@@ -819,9 +819,12 @@
 
         // We put all tasks into drag resizing mode - wait until all of them have completed the
         // drag resizing switch.
-        if (!mService.mWaitingForDrawn.isEmpty()) {
-            mService.mH.removeMessages(H.WAITING_FOR_DRAWN_TIMEOUT);
-            mService.mH.sendEmptyMessageDelayed(H.WAITING_FOR_DRAWN_TIMEOUT,
+        final Runnable existingWaitingForDrwanCallback =
+                mService.mWaitingForDrawnCallbacks.get(mService.mRoot);
+        if (existingWaitingForDrwanCallback != null) {
+            mService.mH.removeMessages(H.WAITING_FOR_DRAWN_TIMEOUT, mService.mRoot);
+            mService.mH.sendMessageDelayed(mService.mH.obtainMessage(H.WAITING_FOR_DRAWN_TIMEOUT,
+                    mService.mRoot),
                     IME_ADJUST_DRAWN_TIMEOUT);
             mAnimationStartDelayed = true;
             if (imeWin != null) {
@@ -838,10 +841,8 @@
             // still gets executed.
             // TODO: Have a real system where we can wait on different windows to be drawn with
             // different callbacks.
-            if (mService.mWaitingForDrawnCallback != null) {
-                mService.mWaitingForDrawnCallback.run();
-            }
-            mService.mWaitingForDrawnCallback = () -> {
+            existingWaitingForDrwanCallback.run();
+            mService.mWaitingForDrawnCallbacks.put(mService.mRoot, () -> {
                 synchronized (mService.mGlobalLock) {
                     mAnimationStartDelayed = false;
                     if (mDelayedImeWin != null) {
@@ -863,7 +864,7 @@
                     notifyAdjustedForImeChanged(
                             mAdjustedForIme || mAdjustedForDivider, duration);
                 }
-            };
+            });
         } else {
             notifyAdjustedForImeChanged(
                     adjustedForIme || adjustedForDivider, IME_ADJUST_ANIM_DURATION);
diff --git a/services/core/java/com/android/server/wm/DragState.java b/services/core/java/com/android/server/wm/DragState.java
index 34820ac..abd7222 100644
--- a/services/core/java/com/android/server/wm/DragState.java
+++ b/services/core/java/com/android/server/wm/DragState.java
@@ -263,7 +263,7 @@
             InputChannel[] channels = InputChannel.openInputChannelPair("drag");
             mServerChannel = channels[0];
             mClientChannel = channels[1];
-            mService.mInputManager.registerInputChannel(mServerChannel, null);
+            mService.mInputManager.registerInputChannel(mServerChannel);
             mInputEventReceiver = new DragInputEventReceiver(mClientChannel,
                     mService.mH.getLooper(), mDragDropController);
 
@@ -272,7 +272,7 @@
             mDragApplicationHandle.dispatchingTimeoutNanos =
                     WindowManagerService.DEFAULT_INPUT_DISPATCHING_TIMEOUT_NANOS;
 
-            mDragWindowHandle = new InputWindowHandle(mDragApplicationHandle, null,
+            mDragWindowHandle = new InputWindowHandle(mDragApplicationHandle,
                     display.getDisplayId());
             mDragWindowHandle.name = "drag";
             mDragWindowHandle.token = mServerChannel.getToken();
diff --git a/services/core/java/com/android/server/wm/EmulatorDisplayOverlay.java b/services/core/java/com/android/server/wm/EmulatorDisplayOverlay.java
index f64592f..2165b0e 100644
--- a/services/core/java/com/android/server/wm/EmulatorDisplayOverlay.java
+++ b/services/core/java/com/android/server/wm/EmulatorDisplayOverlay.java
@@ -50,7 +50,7 @@
     private boolean mVisible;
 
     EmulatorDisplayOverlay(Supplier<Surface> surfaceFactory, Context context, DisplayContent dc,
-            int zOrder) {
+            int zOrder, SurfaceControl.Transaction t) {
         mSurface = surfaceFactory.get();
         final Display display = dc.getDisplay();
         mScreenSize = new Point();
@@ -63,9 +63,9 @@
                     .setBufferSize(mScreenSize.x, mScreenSize.y)
                     .setFormat(PixelFormat.TRANSLUCENT)
                     .build();
-            ctrl.setLayer(zOrder);
-            ctrl.setPosition(0, 0);
-            ctrl.show();
+            t.setLayer(ctrl, zOrder);
+            t.setPosition(ctrl, 0, 0);
+            t.show(ctrl);
             mSurface.copyFrom(ctrl);
         } catch (OutOfResourcesException e) {
         }
@@ -75,7 +75,7 @@
                 com.android.internal.R.drawable.emulator_circular_window_overlay);
     }
 
-    private void drawIfNeeded() {
+    private void drawIfNeeded(SurfaceControl.Transaction t) {
         if (!mDrawNeeded || !mVisible) {
             return;
         }
@@ -92,7 +92,7 @@
             return;
         }
         c.drawColor(Color.TRANSPARENT, PorterDuff.Mode.SRC);
-        mSurfaceControl.setPosition(0, 0);
+        t.setPosition(mSurfaceControl, 0, 0);
         // Always draw the overlay with square dimensions
         int size = Math.max(mScreenSize.x, mScreenSize.y);
         mOverlay.setBounds(0, 0, size, size);
@@ -102,20 +102,20 @@
 
     // Note: caller responsible for being inside
     // Surface.openTransaction() / closeTransaction()
-    public void setVisibility(boolean on) {
+    public void setVisibility(boolean on, SurfaceControl.Transaction t) {
         if (mSurfaceControl == null) {
             return;
         }
         mVisible = on;
-        drawIfNeeded();
+        drawIfNeeded(t);
         if (on) {
-            mSurfaceControl.show();
+            t.show(mSurfaceControl);
         } else {
-            mSurfaceControl.hide();
+            t.hide(mSurfaceControl);
         }
     }
 
-    void positionSurface(int dw, int dh, int rotation) {
+    void positionSurface(int dw, int dh, int rotation, SurfaceControl.Transaction t) {
         if (mLastDW == dw && mLastDH == dh && mRotation == rotation) {
             return;
         }
@@ -123,7 +123,7 @@
         mLastDH = dh;
         mDrawNeeded = true;
         mRotation = rotation;
-        drawIfNeeded();
+        drawIfNeeded(t);
     }
 
 }
diff --git a/services/core/java/com/android/server/wm/ImeInsetsSourceProvider.java b/services/core/java/com/android/server/wm/ImeInsetsSourceProvider.java
new file mode 100644
index 0000000..7e085f6
--- /dev/null
+++ b/services/core/java/com/android/server/wm/ImeInsetsSourceProvider.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.wm;
+
+import android.view.InsetsSource;
+import android.view.WindowInsets;
+
+/**
+ * Controller for IME inset source on the server. It's called provider as it provides the
+ * {@link InsetsSource} to the client that uses it in {@link InsetsSourceConsumer}.
+ */
+class ImeInsetsSourceProvider extends InsetsSourceProvider {
+
+    private WindowState mCurImeTarget;
+    private Runnable mShowImeRunner;
+    private boolean mIsImeLayoutDrawn;
+
+    ImeInsetsSourceProvider(InsetsSource source,
+            InsetsStateController stateController, DisplayContent displayContent) {
+        super(source, stateController, displayContent);
+    }
+
+    /**
+     * Called when a layout pass has occurred.
+     */
+    void onPostLayout() {
+        super.onPostLayout();
+
+        if (mCurImeTarget != null
+                && mCurImeTarget == mDisplayContent.mInputMethodTarget
+                && mWin != null
+                && mWin.isDrawnLw()
+                && !mWin.mGivenInsetsPending) {
+            mIsImeLayoutDrawn = true;
+        }
+    }
+
+    /**
+     * Called when Insets have been dispatched to client.
+     */
+    void onPostInsetsDispatched() {
+        if (mIsImeLayoutDrawn && mShowImeRunner != null) {
+            // Show IME if InputMethodService requested to be shown and it's layout has finished.
+            mShowImeRunner.run();
+            mIsImeLayoutDrawn = false;
+            mShowImeRunner = null;
+        }
+    }
+
+    /**
+     * Called from {@link WindowManagerInternal#showImePostLayout} when {@link InputMethodService}
+     * requests to show IME on {@param imeTarget}.
+     * @param imeTarget imeTarget on which IME is displayed.
+     */
+    void scheduleShowImePostLayout(WindowState imeTarget) {
+        mCurImeTarget = imeTarget;
+        mShowImeRunner = () -> {
+            // Target should still be the same.
+            if (mCurImeTarget == mDisplayContent.mInputMethodTarget) {
+                mDisplayContent.mInputMethodTarget.showInsets(
+                        WindowInsets.Type.ime(), true /* fromIme */);
+            }
+            mCurImeTarget = null;
+        };
+    }
+
+}
diff --git a/services/core/java/com/android/server/wm/InputConsumerImpl.java b/services/core/java/com/android/server/wm/InputConsumerImpl.java
index 8dae016..ebe9f08 100644
--- a/services/core/java/com/android/server/wm/InputConsumerImpl.java
+++ b/services/core/java/com/android/server/wm/InputConsumerImpl.java
@@ -65,14 +65,14 @@
         } else {
             mClientChannel = channels[1];
         }
-        mService.mInputManager.registerInputChannel(mServerChannel, null);
+        mService.mInputManager.registerInputChannel(mServerChannel);
 
         mApplicationHandle = new InputApplicationHandle(new Binder());
         mApplicationHandle.name = name;
         mApplicationHandle.dispatchingTimeoutNanos =
                 WindowManagerService.DEFAULT_INPUT_DISPATCHING_TIMEOUT_NANOS;
 
-        mWindowHandle = new InputWindowHandle(mApplicationHandle, null, displayId);
+        mWindowHandle = new InputWindowHandle(mApplicationHandle, displayId);
         mWindowHandle.name = name;
         mWindowHandle.token = mServerChannel.getToken();
         mWindowHandle.layoutParamsType = WindowManager.LayoutParams.TYPE_INPUT_CONSUMER;
diff --git a/services/core/java/com/android/server/wm/InputManagerCallback.java b/services/core/java/com/android/server/wm/InputManagerCallback.java
index ec36a82..eb9b3e9 100644
--- a/services/core/java/com/android/server/wm/InputManagerCallback.java
+++ b/services/core/java/com/android/server/wm/InputManagerCallback.java
@@ -5,20 +5,25 @@
 import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY;
 
 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_INPUT;
+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.ON_POINTER_DOWN_OUTSIDE_FOCUS;
 
 import android.os.Debug;
 import android.os.IBinder;
+import android.os.RemoteException;
 import android.util.Slog;
+import android.view.IWindow;
 import android.view.KeyEvent;
 import android.view.WindowManager;
 
 import com.android.server.input.InputManagerService;
 
 import java.io.PrintWriter;
+import java.util.concurrent.atomic.AtomicReference;
 
 final class InputManagerCallback implements InputManagerService.WindowManagerCallbacks {
+    private static final String TAG = TAG_WITH_CLASS_NAME ? "InputManagerCallback" : TAG_WM;
     private final WindowManagerService mService;
 
     // Set to true when the first input device configuration change notification
@@ -37,6 +42,13 @@
     // which point the ActivityManager will enable dispatching.
     private boolean mInputDispatchEnabled;
 
+    // TODO(b/141749603)) investigate if this can be part of client focus change dispatch
+    // Tracks the currently focused window used to update pointer capture state in clients
+    private AtomicReference<IWindow> mFocusedWindow = new AtomicReference<>();
+
+    // Tracks focused window pointer capture state
+    private boolean mFocusedWindowHasCapture;
+
     public InputManagerCallback(WindowManagerService service) {
         mService = service;
     }
@@ -53,7 +65,7 @@
         }
 
         synchronized (mService.mGlobalLock) {
-            WindowState windowState = mService.windowForClientLocked(null, token, false);
+            WindowState windowState = mService.mInputToWindowMap.get(token);
             if (windowState != null) {
                 Slog.i(TAG_WM, "WINDOW DIED " + windowState);
                 windowState.removeIfPossible();
@@ -72,9 +84,10 @@
         AppWindowToken appWindowToken = null;
         WindowState windowState = null;
         boolean aboveSystem = false;
+        //TODO(b/141764879) Limit scope of wm lock when input calls notifyANR
         synchronized (mService.mGlobalLock) {
             if (token != null) {
-                windowState = mService.windowForClientLocked(null, token, false);
+                windowState = mService.mInputToWindowMap.get(token);
                 if (windowState != null) {
                     appWindowToken = windowState.mAppToken;
                 }
@@ -109,7 +122,7 @@
             // Notify the activity manager about the timeout and let it decide whether
             // to abort dispatching or keep waiting.
             final boolean abort = appWindowToken.keyDispatchingTimedOut(reason,
-                    (windowState != null) ? windowState.mSession.mPid : -1);
+                    windowState.mSession.mPid);
             if (!abort) {
                 // The activity manager declined to abort dispatching.
                 // Wait a bit longer and timeout again later.
@@ -239,6 +252,59 @@
         mService.mH.obtainMessage(ON_POINTER_DOWN_OUTSIDE_FOCUS, touchedToken).sendToTarget();
     }
 
+    @Override
+    public boolean notifyFocusChanged(IBinder oldToken, IBinder newToken) {
+        boolean requestRefreshConfiguration = false;
+        final IWindow newFocusedWindow;
+        final WindowState win;
+
+        // TODO(b/141749603) investigate if this can be part of client focus change dispatch
+        synchronized (mService.mGlobalLock) {
+            win = mService.mInputToWindowMap.get(newToken);
+        }
+        newFocusedWindow = (win != null) ? win.mClient : null;
+
+        final IWindow focusedWindow = mFocusedWindow.get();
+        if (focusedWindow != null) {
+            if (focusedWindow.asBinder() == newFocusedWindow.asBinder()) {
+                Slog.w(TAG, "notifyFocusChanged called with unchanged mFocusedWindow="
+                        + focusedWindow);
+                return false;
+            }
+            requestRefreshConfiguration = dispatchPointerCaptureChanged(focusedWindow, false);
+        }
+        mFocusedWindow.set(newFocusedWindow);
+        return requestRefreshConfiguration;
+    }
+
+    @Override
+    public boolean requestPointerCapture(IBinder windowToken, boolean enabled) {
+        final IWindow focusedWindow = mFocusedWindow.get();
+        if (focusedWindow == null || focusedWindow.asBinder() != windowToken) {
+            Slog.e(TAG, "requestPointerCapture called for a window that has no focus: "
+                    + windowToken);
+            return false;
+        }
+        if (mFocusedWindowHasCapture == enabled) {
+            Slog.i(TAG, "requestPointerCapture: already " + (enabled ? "enabled" : "disabled"));
+            return false;
+        }
+        return dispatchPointerCaptureChanged(focusedWindow, enabled);
+    }
+
+    private boolean dispatchPointerCaptureChanged(IWindow focusedWindow, boolean enabled) {
+        if (mFocusedWindowHasCapture != enabled) {
+            mFocusedWindowHasCapture = enabled;
+            try {
+                focusedWindow.dispatchPointerCaptureChanged(enabled);
+            } catch (RemoteException ex) {
+                /* ignore */
+            }
+            return true;
+        }
+        return false;
+    }
+
     /** Waits until the built-in input devices have been configured. */
     public boolean waitForInputDevicesReady(long timeoutMillis) {
         synchronized (mInputDevicesReadyMonitor) {
diff --git a/services/core/java/com/android/server/wm/InputMonitor.java b/services/core/java/com/android/server/wm/InputMonitor.java
index 932b4fa..dc9a598 100644
--- a/services/core/java/com/android/server/wm/InputMonitor.java
+++ b/services/core/java/com/android/server/wm/InputMonitor.java
@@ -411,7 +411,7 @@
         WallpaperController wallpaperController;
 
         // An invalid window handle that tells SurfaceFlinger not update the input info.
-        final InputWindowHandle mInvalidInputWindow = new InputWindowHandle(null, null, mDisplayId);
+        final InputWindowHandle mInvalidInputWindow = new InputWindowHandle(null, mDisplayId);
 
         private void updateInputWindows(boolean inDrag) {
             Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER, "updateInputWindows");
diff --git a/services/core/java/com/android/server/wm/InsetsControlTarget.java b/services/core/java/com/android/server/wm/InsetsControlTarget.java
index 3db6dcf..b7184a5 100644
--- a/services/core/java/com/android/server/wm/InsetsControlTarget.java
+++ b/services/core/java/com/android/server/wm/InsetsControlTarget.java
@@ -16,9 +16,21 @@
 
 package com.android.server.wm;
 
+import android.inputmethodservice.InputMethodService;
+import android.view.WindowInsets.Type.InsetType;
+
 /**
  * Generalization of an object that can control insets state.
  */
 interface InsetsControlTarget {
     void notifyInsetsControlChanged();
+
+    /**
+     * Instructs the control target to show inset sources.
+     *
+     * @param types to specify which types of insets source window should be shown.
+     * @param fromIme {@code true} if IME show request originated from {@link InputMethodService}.
+     */
+    default void showInsets(@InsetType int types, boolean fromIme) {
+    }
 }
diff --git a/services/core/java/com/android/server/wm/InsetsSourceProvider.java b/services/core/java/com/android/server/wm/InsetsSourceProvider.java
index 8426864..3731d3f 100644
--- a/services/core/java/com/android/server/wm/InsetsSourceProvider.java
+++ b/services/core/java/com/android/server/wm/InsetsSourceProvider.java
@@ -47,9 +47,11 @@
  */
 class InsetsSourceProvider {
 
+    protected final DisplayContent mDisplayContent;
+    protected final @NonNull InsetsSource mSource;
+    protected WindowState mWin;
+
     private final Rect mTmpRect = new Rect();
-    private final @NonNull InsetsSource mSource;
-    private final DisplayContent mDisplayContent;
     private final InsetsStateController mStateController;
     private final InsetsSourceControl mFakeControl;
     private @Nullable InsetsSourceControl mControl;
@@ -57,7 +59,6 @@
     private @Nullable InsetsControlTarget mFakeControlTarget;
 
     private @Nullable ControlAdapter mAdapter;
-    private WindowState mWin;
     private TriConsumer<DisplayFrames, WindowState, Rect> mFrameProvider;
 
     /** The visibility override from the current controlling window. */
@@ -240,6 +241,10 @@
         @Override
         public void startAnimation(SurfaceControl animationLeash, Transaction t,
                 OnAnimationFinishedCallback finishCallback) {
+            // TODO: use 0 alpha and remove t.hide() once b/138459974 is fixed.
+            t.setAlpha(animationLeash, 1 /* alpha */);
+            t.hide(animationLeash);
+
             mCapturedLeash = animationLeash;
             final Rect frame = mWin.getWindowFrames().mFrame;
             t.setPosition(mCapturedLeash, frame.left, frame.top);
diff --git a/services/core/java/com/android/server/wm/InsetsStateController.java b/services/core/java/com/android/server/wm/InsetsStateController.java
index 4ebb553..b0410335c 100644
--- a/services/core/java/com/android/server/wm/InsetsStateController.java
+++ b/services/core/java/com/android/server/wm/InsetsStateController.java
@@ -108,8 +108,18 @@
      * @return The provider of a specific type.
      */
     InsetsSourceProvider getSourceProvider(@InternalInsetType int type) {
-        return mProviders.computeIfAbsent(type,
-                key -> new InsetsSourceProvider(mState.getSource(key), this, mDisplayContent));
+        if (type == TYPE_IME) {
+            return mProviders.computeIfAbsent(type,
+                    key -> new ImeInsetsSourceProvider(
+                            mState.getSource(key), this, mDisplayContent));
+        } else {
+            return mProviders.computeIfAbsent(type,
+                    key -> new InsetsSourceProvider(mState.getSource(key), this, mDisplayContent));
+        }
+    }
+
+    ImeInsetsSourceProvider getImeSourceProvider() {
+        return (ImeInsetsSourceProvider) getSourceProvider(TYPE_IME);
     }
 
     /**
@@ -124,6 +134,7 @@
             mLastState.set(mState, true /* copySources */);
             notifyInsetsChanged();
         }
+        getImeSourceProvider().onPostInsetsDispatched();
     }
 
     void onInsetsModified(WindowState windowState, InsetsState state) {
diff --git a/services/core/java/com/android/server/wm/LaunchParamsPersister.java b/services/core/java/com/android/server/wm/LaunchParamsPersister.java
index d364a37..5d27390 100644
--- a/services/core/java/com/android/server/wm/LaunchParamsPersister.java
+++ b/services/core/java/com/android/server/wm/LaunchParamsPersister.java
@@ -17,7 +17,6 @@
 package com.android.server.wm;
 
 import android.content.ComponentName;
-import android.content.pm.PackageList;
 import android.content.pm.PackageManagerInternal;
 import android.graphics.Rect;
 import android.os.Environment;
@@ -32,6 +31,7 @@
 import com.android.internal.annotations.VisibleForTesting;
 import com.android.internal.util.FastXmlSerializer;
 import com.android.server.LocalServices;
+import com.android.server.pm.PackageList;
 import com.android.server.wm.LaunchParamsController.LaunchParams;
 
 import libcore.io.IoUtils;
@@ -198,7 +198,7 @@
 
     void saveTask(TaskRecord task) {
         final ComponentName name = task.realActivity;
-        final int userId = task.userId;
+        final int userId = task.mUserId;
         PersistableLaunchParams params;
         ArrayMap<ComponentName, PersistableLaunchParams> map = mMap.get(userId);
         if (map == null) {
@@ -247,7 +247,7 @@
 
     void getLaunchParams(TaskRecord task, ActivityRecord activity, LaunchParams outParams) {
         final ComponentName name = task != null ? task.realActivity : activity.mActivityComponent;
-        final int userId = task != null ? task.userId : activity.mUserId;
+        final int userId = task != null ? task.mUserId : activity.mUserId;
 
         outParams.reset();
         Map<ComponentName, PersistableLaunchParams> map = mMap.get(userId);
diff --git a/services/core/java/com/android/server/wm/Letterbox.java b/services/core/java/com/android/server/wm/Letterbox.java
index 1bd2493..c59a73b 100644
--- a/services/core/java/com/android/server/wm/Letterbox.java
+++ b/services/core/java/com/android/server/wm/Letterbox.java
@@ -20,7 +20,7 @@
 
 import android.graphics.Point;
 import android.graphics.Rect;
-import android.os.Binder;
+import android.os.IBinder;
 import android.os.Process;
 import android.view.InputChannel;
 import android.view.InputEventReceiver;
@@ -170,7 +170,7 @@
         final InputWindowHandle mWindowHandle;
         final InputEventReceiver mInputEventReceiver;
         final WindowManagerService mWmService;
-        final Binder mToken = new Binder();
+        final IBinder mToken;
 
         InputInterceptor(String namePrefix, WindowState win) {
             mWmService = win.mWmService;
@@ -180,10 +180,11 @@
             mClientChannel = channels[1];
             mInputEventReceiver = new SimpleInputReceiver(mClientChannel);
 
-            mWmService.mInputManager.registerInputChannel(mServerChannel, mToken);
+            mWmService.mInputManager.registerInputChannel(mServerChannel);
+            mToken = mServerChannel.getToken();
 
             mWindowHandle = new InputWindowHandle(null /* inputApplicationHandle */,
-                    null /* clientWindow */, win.getDisplayId());
+                    win.getDisplayId());
             mWindowHandle.name = name;
             mWindowHandle.token = mToken;
             mWindowHandle.layoutParamsFlags = WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
@@ -247,12 +248,12 @@
             mLayoutFrameRelative.offset(-surfaceOrigin.x, -surfaceOrigin.y);
         }
 
-        private void createSurface() {
+        private void createSurface(SurfaceControl.Transaction t) {
             mSurface = mSurfaceControlFactory.get().setName("Letterbox - " + mType)
                     .setFlags(HIDDEN).setColorLayer().build();
-            mSurface.setLayer(-1);
-            mSurface.setColor(new float[]{0, 0, 0});
-            mSurface.setColorSpaceAgnostic(true);
+            t.setLayer(mSurface, -1)
+                    .setColor(mSurface, new float[]{0, 0, 0})
+                    .setColorSpaceAgnostic(mSurface, true);
         }
 
         void attachInput(WindowState win) {
@@ -300,7 +301,7 @@
             mSurfaceFrameRelative.set(mLayoutFrameRelative);
             if (!mSurfaceFrameRelative.isEmpty()) {
                 if (mSurface == null) {
-                    createSurface();
+                    createSurface(t);
                 }
                 t.setPosition(mSurface, mSurfaceFrameRelative.left, mSurfaceFrameRelative.top);
                 t.setWindowCrop(mSurface, mSurfaceFrameRelative.width(),
diff --git a/services/core/java/com/android/server/wm/LockTaskController.java b/services/core/java/com/android/server/wm/LockTaskController.java
index b30da5e..dc45686 100644
--- a/services/core/java/com/android/server/wm/LockTaskController.java
+++ b/services/core/java/com/android/server/wm/LockTaskController.java
@@ -317,12 +317,12 @@
         }
 
         // Allow recents activity if enabled by policy
-        if (task.isActivityTypeRecents() && isRecentsAllowed(task.userId)) {
+        if (task.isActivityTypeRecents() && isRecentsAllowed(task.mUserId)) {
             return false;
         }
 
         // Allow emergency calling when the device is protected by a locked keyguard
-        if (isKeyguardAllowed(task.userId) && isEmergencyCallTask(task)) {
+        if (isKeyguardAllowed(task.mUserId) && isEmergencyCallTask(task)) {
             return false;
         }
 
@@ -474,7 +474,7 @@
         if (mLockTaskModeTasks.isEmpty()) {
             if (DEBUG_LOCKTASK) Slog.d(TAG_LOCKTASK, "removeLockedTask: task=" + task +
                     " last task, reverting locktask mode. Callers=" + Debug.getCallers(3));
-            mHandler.post(() -> performStopLockTask(task.userId));
+            mHandler.post(() -> performStopLockTask(task.mUserId));
         }
     }
 
@@ -537,7 +537,7 @@
                 StatusBarManagerInternal statusBarManager = LocalServices.getService(
                         StatusBarManagerInternal.class);
                 if (statusBarManager != null) {
-                    statusBarManager.showScreenPinningRequest(task.taskId);
+                    statusBarManager.showScreenPinningRequest(task.mTaskId);
                 }
                 return;
             }
@@ -570,11 +570,11 @@
 
         final Intent taskIntent = task.intent;
         if (mLockTaskModeTasks.isEmpty() && taskIntent != null) {
-            mSupervisor.mRecentTasks.onLockTaskModeStateChanged(lockTaskModeState, task.userId);
+            mSupervisor.mRecentTasks.onLockTaskModeStateChanged(lockTaskModeState, task.mUserId);
             // Start lock task on the handler thread
             mHandler.post(() -> performStartLockTask(
                     taskIntent.getComponent().getPackageName(),
-                    task.userId,
+                    task.mUserId,
                     lockTaskModeState));
         }
         if (DEBUG_LOCKTASK) Slog.w(TAG_LOCKTASK, "setLockTaskMode: Locking to " + task +
@@ -640,7 +640,7 @@
                     || lockedTask.mLockTaskAuth == LOCK_TASK_AUTH_WHITELISTED;
 
             if (mLockTaskModeState != LOCK_TASK_MODE_LOCKED
-                    || lockedTask.userId != userId
+                    || lockedTask.mUserId != userId
                     || !wasWhitelisted || isWhitelisted) {
                 continue;
             }
@@ -704,7 +704,7 @@
         }
 
         mLockTaskFeatures.put(userId, flags);
-        if (!mLockTaskModeTasks.isEmpty() && userId == mLockTaskModeTasks.get(0).userId) {
+        if (!mLockTaskModeTasks.isEmpty() && userId == mLockTaskModeTasks.get(0).mUserId) {
             mHandler.post(() -> {
                 if (mLockTaskModeState == LOCK_TASK_MODE_LOCKED) {
                     setStatusBarState(mLockTaskModeState, userId);
diff --git a/services/core/java/com/android/server/wm/ProtoLogGroup.java b/services/core/java/com/android/server/wm/ProtoLogGroup.java
index 2e0ef14..f5a1884 100644
--- a/services/core/java/com/android/server/wm/ProtoLogGroup.java
+++ b/services/core/java/com/android/server/wm/ProtoLogGroup.java
@@ -28,7 +28,7 @@
  */
 public enum ProtoLogGroup implements IProtoLogGroup {
     WM_ERROR(true, true, true, Consts.TAG_WM),
-    WM_DEBUG_ORIENTATION(Consts.ENABLE_DEBUG, Consts.ENABLE_LOG_TO_PROTO_DEBUG, true,
+    WM_DEBUG_ORIENTATION(Consts.ENABLE_DEBUG, Consts.ENABLE_LOG_TO_PROTO_DEBUG, false,
             Consts.TAG_WM),
     WM_DEBUG_FOCUS_LIGHT(Consts.ENABLE_DEBUG, Consts.ENABLE_LOG_TO_PROTO_DEBUG, false,
             Consts.TAG_WM),
@@ -129,7 +129,7 @@
     private static class Consts {
         private static final String TAG_WM = "WindowManager";
 
-        private static final boolean ENABLE_DEBUG = true;
+        private static final boolean ENABLE_DEBUG = false;
         private static final boolean ENABLE_LOG_TO_PROTO_DEBUG = true;
     }
 }
diff --git a/services/core/java/com/android/server/wm/RecentTasks.java b/services/core/java/com/android/server/wm/RecentTasks.java
index fb6b5da..7169677 100644
--- a/services/core/java/com/android/server/wm/RecentTasks.java
+++ b/services/core/java/com/android/server/wm/RecentTasks.java
@@ -120,7 +120,7 @@
 
     // Comparator to sort by taskId
     private static final Comparator<TaskRecord> TASK_ID_COMPARATOR =
-            (lhs, rhs) -> rhs.taskId - lhs.taskId;
+            (lhs, rhs) -> rhs.mTaskId - lhs.mTaskId;
 
     // Placeholder variables to keep track of activities/apps that are no longer avialble while
     // iterating through the recents list
@@ -272,9 +272,14 @@
      * app, or a timeout occurs.
      */
     void setFreezeTaskListReordering() {
+        // Only fire the callback once per quickswitch session, not on every individual switch
+        if (!mFreezeTaskListReordering) {
+            mTaskNotificationController.notifyTaskListFrozen(true);
+            mFreezeTaskListReordering = true;
+        }
+
         // Always update the reordering time when this is called to ensure that the timeout
         // is reset
-        mFreezeTaskListReordering = true;
         mService.mH.removeCallbacks(mResetFreezeTaskListOnTimeoutRunnable);
         mService.mH.postDelayed(mResetFreezeTaskListOnTimeoutRunnable, mFreezeTaskListTimeoutMs);
     }
@@ -302,6 +307,7 @@
         trimInactiveRecentTasks();
 
         mTaskNotificationController.notifyTaskStackChanged();
+        mTaskNotificationController.notifyTaskListFrozen(false);
     }
 
     /**
@@ -458,8 +464,8 @@
         // Check if any tasks are added before recents is loaded
         final SparseBooleanArray preaddedTasks = new SparseBooleanArray();
         for (final TaskRecord task : mTasks) {
-            if (task.userId == userId && shouldPersistTaskLocked(task)) {
-                preaddedTasks.put(task.taskId, true);
+            if (task.mUserId == userId && shouldPersistTaskLocked(task)) {
+                preaddedTasks.put(task.mTaskId, true);
             }
         }
 
@@ -527,12 +533,12 @@
             if (shouldPersistTaskLocked(task)) {
                 // Set of persisted taskIds for task.userId should not be null here
                 // TODO Investigate why it can happen. For now initialize with an empty set
-                if (mPersistedTaskIds.get(task.userId) == null) {
-                    Slog.wtf(TAG, "No task ids found for userId " + task.userId + ". task=" + task
+                if (mPersistedTaskIds.get(task.mUserId) == null) {
+                    Slog.wtf(TAG, "No task ids found for userId " + task.mUserId + ". task=" + task
                             + " mPersistedTaskIds=" + mPersistedTaskIds);
-                    mPersistedTaskIds.put(task.userId, new SparseBooleanArray());
+                    mPersistedTaskIds.put(task.mUserId, new SparseBooleanArray());
                 }
-                mPersistedTaskIds.get(task.userId).put(task.taskId, true);
+                mPersistedTaskIds.get(task.mUserId).put(task.mTaskId, true);
             }
         }
     }
@@ -608,7 +614,7 @@
 
         for (int i = mTasks.size() - 1; i >= 0; --i) {
             TaskRecord tr = mTasks.get(i);
-            if (tr.userId == userId) {
+            if (tr.mUserId == userId) {
                 if(DEBUG_TASKS) Slog.i(TAG_TASKS,
                         "remove RecentTask " + tr + " when finishing user" + userId);
                 remove(tr);
@@ -622,11 +628,11 @@
             final TaskRecord tr = mTasks.get(i);
             if (tr.realActivity != null
                     && packageNames.contains(tr.realActivity.getPackageName())
-                    && tr.userId == userId
+                    && tr.mUserId == userId
                     && tr.realActivitySuspended != suspended) {
                tr.realActivitySuspended = suspended;
                if (suspended) {
-                   mSupervisor.removeTaskByIdLocked(tr.taskId, false,
+                   mSupervisor.removeTaskByIdLocked(tr.mTaskId, false,
                            REMOVE_FROM_RECENTS, "suspended-package");
                }
                notifyTaskPersisterLocked(tr, false);
@@ -640,7 +646,7 @@
         }
         for (int i = mTasks.size() - 1; i >= 0; --i) {
             final TaskRecord tr = mTasks.get(i);
-            if (tr.userId == userId && !mService.getLockTaskController().isTaskWhitelisted(tr)) {
+            if (tr.mUserId == userId && !mService.getLockTaskController().isTaskWhitelisted(tr)) {
                 remove(tr);
             }
         }
@@ -651,10 +657,10 @@
             final TaskRecord tr = mTasks.get(i);
             final String taskPackageName =
                     tr.getBaseIntent().getComponent().getPackageName();
-            if (tr.userId != userId) continue;
+            if (tr.mUserId != userId) continue;
             if (!taskPackageName.equals(packageName)) continue;
 
-            mSupervisor.removeTaskByIdLocked(tr.taskId, true, REMOVE_FROM_RECENTS,
+            mSupervisor.removeTaskByIdLocked(tr.mTaskId, true, REMOVE_FROM_RECENTS,
                     "remove-package-task");
         }
     }
@@ -663,7 +669,7 @@
         Set<Integer> profileIds = getProfileIds(userId);
         for (int i = mTasks.size() - 1; i >= 0; --i) {
             final TaskRecord tr = mTasks.get(i);
-            if (!profileIds.contains(tr.userId)) continue;
+            if (!profileIds.contains(tr.mUserId)) continue;
             if (isVisibleRecentTask(tr)) {
                 mTasks.remove(i);
                 notifyTaskRemoved(tr, true /* wasTrimmed */, true /* killProcess */);
@@ -675,7 +681,7 @@
             int userId) {
         for (int i = mTasks.size() - 1; i >= 0; --i) {
             final TaskRecord tr = mTasks.get(i);
-            if (userId != UserHandle.USER_ALL && tr.userId != userId) {
+            if (userId != UserHandle.USER_ALL && tr.mUserId != userId) {
                 continue;
             }
 
@@ -683,7 +689,7 @@
             final boolean sameComponent = cn != null && cn.getPackageName().equals(packageName)
                     && (filterByClasses == null || filterByClasses.contains(cn.getClassName()));
             if (sameComponent) {
-                mSupervisor.removeTaskByIdLocked(tr.taskId, false,
+                mSupervisor.removeTaskByIdLocked(tr.mTaskId, false,
                         REMOVE_FROM_RECENTS, "disabled-package");
             }
         }
@@ -709,7 +715,7 @@
         final IPackageManager pm = AppGlobals.getPackageManager();
         for (int i = recentsCount - 1; i >= 0; i--) {
             final TaskRecord task = mTasks.get(i);
-            if (userId != UserHandle.USER_ALL && task.userId != userId) {
+            if (userId != UserHandle.USER_ALL && task.mUserId != userId) {
                 // Only look at tasks for the user ID of interest.
                 continue;
             }
@@ -826,7 +832,7 @@
             if (intent == null || !callingPackage.equals(intent.getComponent().getPackageName())) {
                 continue;
             }
-            AppTaskImpl taskImpl = new AppTaskImpl(mService, tr.taskId, callingUid);
+            AppTaskImpl taskImpl = new AppTaskImpl(mService, tr.mTaskId, callingUid);
             list.add(taskImpl.asBinder());
         }
         return list;
@@ -908,7 +914,7 @@
             }
 
             // Only add calling user or related users recent tasks
-            if (!includedUsers.contains(Integer.valueOf(tr.userId))) {
+            if (!includedUsers.contains(Integer.valueOf(tr.mUserId))) {
                 if (DEBUG_RECENTS) Slog.d(TAG_RECENTS, "Skipping, not user: " + tr);
                 continue;
             }
@@ -972,7 +978,7 @@
             if ((task.isPersistable || task.inRecents)
                     && (stack == null || !stack.isHomeOrRecentsStack())) {
                 if (TaskPersister.DEBUG) Slog.d(TAG, "adding to persistentTaskIds task=" + task);
-                persistentTaskIds.add(task.taskId);
+                persistentTaskIds.add(task.mTaskId);
             } else {
                 if (TaskPersister.DEBUG) Slog.d(TAG, "omitting from persistentTaskIds task="
                         + task);
@@ -997,7 +1003,7 @@
             if (isVisibleRecentTask(tr)) {
                 numVisibleTasks++;
                 if (isInVisibleRange(tr, i, numVisibleTasks, false /* skipExcludedCheck */)) {
-                    res.put(tr.taskId, true);
+                    res.put(tr.mTaskId, true);
                 }
             }
         }
@@ -1011,7 +1017,7 @@
         final int recentsCount = mTasks.size();
         for (int i = 0; i < recentsCount; i++) {
             TaskRecord tr = mTasks.get(i);
-            if (tr.taskId == id) {
+            if (tr.mTaskId == id) {
                 return tr;
             }
         }
@@ -1024,7 +1030,7 @@
     void add(TaskRecord task) {
         if (DEBUG_RECENTS_TRIM_TASKS) Slog.d(TAG, "add: task=" + task);
 
-        final boolean isAffiliated = task.mAffiliatedTaskId != task.taskId
+        final boolean isAffiliated = task.mAffiliatedTaskId != task.mTaskId
                 || task.mNextAffiliateTaskId != INVALID_TASK_ID
                 || task.mPrevAffiliateTaskId != INVALID_TASK_ID;
 
@@ -1138,7 +1144,7 @@
 
         if (needAffiliationFix) {
             if (DEBUG_RECENTS) Slog.d(TAG_RECENTS, "addRecent: regrouping affiliations");
-            cleanupLocked(task.userId);
+            cleanupLocked(task.mUserId);
         }
 
         // Trim the set of tasks to the active set
@@ -1248,13 +1254,13 @@
         if (DEBUG_RECENTS_TRIM_TASKS) Slog.d(TAG, "isActiveRecentTask: task=" + task
                 + " globalMax=" + mGlobalMaxNumTasks);
 
-        if (quietProfileUserIds.get(task.userId)) {
+        if (quietProfileUserIds.get(task.mUserId)) {
             // Quiet profile user's tasks are never active
             if (DEBUG_RECENTS_TRIM_TASKS) Slog.d(TAG, "\tisQuietProfileTask=true");
             return false;
         }
 
-        if (task.mAffiliatedTaskId != INVALID_TASK_ID && task.mAffiliatedTaskId != task.taskId) {
+        if (task.mAffiliatedTaskId != INVALID_TASK_ID && task.mAffiliatedTaskId != task.mTaskId) {
             // Keep the task active if its affiliated task is also active
             final TaskRecord affiliatedTask = getTask(task.mAffiliatedTaskId);
             if (affiliatedTask != null) {
@@ -1430,7 +1436,7 @@
             final TaskRecord tr = mTasks.get(i);
             if (task != tr) {
                 if (!hasCompatibleActivityTypeAndWindowingMode(task, tr)
-                        || task.userId != tr.userId) {
+                        || task.mUserId != tr.mUserId) {
                     continue;
                 }
                 final Intent trIntent = tr.intent;
@@ -1485,7 +1491,7 @@
         final int affiliateId = startTask.mAffiliatedTaskId;
 
         // Quick identification of isolated tasks. I.e. those not launched behind.
-        if (startTask.taskId == affiliateId && startTask.mPrevAffiliate == null &&
+        if (startTask.mTaskId == affiliateId && startTask.mPrevAffiliate == null &&
                 startTask.mNextAffiliate == null) {
             // There is still a slim chance that there are other tasks that point to this task
             // and that the chain is so messed up that this task no longer points to them but
@@ -1581,7 +1587,7 @@
             } else {
                 // Verify middle of the chain's next points back to the one before.
                 if (cur.mNextAffiliate != prev
-                        || cur.mNextAffiliateTaskId != prev.taskId) {
+                        || cur.mNextAffiliateTaskId != prev.mTaskId) {
                     Slog.wtf(TAG, "Bad chain @" + endIndex
                             + ": middle task " + cur + " @" + endIndex
                             + " has bad next affiliate "
diff --git a/services/core/java/com/android/server/wm/RecentsAnimation.java b/services/core/java/com/android/server/wm/RecentsAnimation.java
index 31f4584..062cdc5 100644
--- a/services/core/java/com/android/server/wm/RecentsAnimation.java
+++ b/services/core/java/com/android/server/wm/RecentsAnimation.java
@@ -137,9 +137,9 @@
             mStackSupervisor.startSpecificActivityLocked(targetActivity, false /* andResume */,
                     false /* checkConfig */);
             // Make sure the activity won't be involved in transition.
-            if (targetActivity.mAppWindowToken != null) {
-                targetActivity.mAppWindowToken.getDisplayContent().mUnknownAppVisibilityController
-                        .appRemovedOrHidden(targetActivity.mAppWindowToken);
+            if (targetActivity.getDisplayContent() != null) {
+                targetActivity.getDisplayContent().mUnknownAppVisibilityController
+                        .appRemovedOrHidden(targetActivity);
             }
         }
 
@@ -429,7 +429,7 @@
         // 1) The next launching task is not being animated by the recents animation
         // 2) The next task is home activity. (i.e. pressing home key to back home in recents).
         if ((!controller.isAnimatingTask(stack.getTaskStack().getTopChild())
-                || controller.isTargetApp(stack.getTopActivity().mAppWindowToken))
+                || controller.isTargetApp(stack.getTopActivity()))
                 && controller.shouldDeferCancelUntilNextTransition()) {
             // Always prepare an app transition since we rely on the transition callbacks to cleanup
             mWindowManager.prepareAppTransition(TRANSIT_NONE, false);
@@ -492,7 +492,7 @@
 
         for (int i = targetStack.getChildCount() - 1; i >= 0; i--) {
             final TaskRecord task = targetStack.getChildAt(i);
-            if (task.userId == mUserId
+            if (task.mUserId == mUserId
                     && task.getBaseIntent().getComponent().equals(mTargetIntent.getComponent())) {
                 return task.getTopActivity();
             }
diff --git a/services/core/java/com/android/server/wm/RootActivityContainer.java b/services/core/java/com/android/server/wm/RootActivityContainer.java
index 734f224..d78d517 100644
--- a/services/core/java/com/android/server/wm/RootActivityContainer.java
+++ b/services/core/java/com/android/server/wm/RootActivityContainer.java
@@ -638,17 +638,23 @@
         if (displayContent != null) {
             config = displayContent.updateOrientation(
                     getDisplayOverrideConfiguration(displayId),
-                    starting != null && starting.mayFreezeScreenLocked(starting.app)
+                    starting != null && starting.mayFreezeScreenLocked()
                             ? starting.appToken : null,
                     true /* forceUpdate */);
         }
+        // Visibilities may change so let the starting activity have a chance to report. Can't do it
+        // when visibility is changed in each AppWindowToken because it may trigger wrong
+        // configuration push because the visibility of some activities may not be updated yet.
+        if (starting != null) {
+            starting.reportDescendantOrientationChangeIfNeeded();
+        }
         if (starting != null && markFrozenIfConfigChanged && config != null) {
             starting.frozenBeforeDestroy = true;
         }
 
-        if (displayContent != null && displayContent.mAcitvityDisplay != null) {
+        if (displayContent != null && displayContent.mActivityDisplay != null) {
             // Update the configuration of the activities on the display.
-            return displayContent.mAcitvityDisplay.updateDisplayOverrideConfigurationLocked(config,
+            return displayContent.mActivityDisplay.updateDisplayOverrideConfigurationLocked(config,
                     starting, deferResume, null /* result */);
         } else {
             return true;
@@ -1097,7 +1103,7 @@
                 }
             }
         }
-        return finishedTask != null ? finishedTask.taskId : INVALID_TASK_ID;
+        return finishedTask != null ? finishedTask.mTaskId : INVALID_TASK_ID;
     }
 
     boolean resumeFocusedStacksTopActivities() {
@@ -1254,14 +1260,14 @@
         int[] taskUserIds = new int[numTasks];
         for (int i = 0; i < numTasks; ++i) {
             final TaskRecord task = tasks.get(i);
-            taskIds[i] = task.taskId;
+            taskIds[i] = task.mTaskId;
             taskNames[i] = task.origActivity != null ? task.origActivity.flattenToString()
                     : task.realActivity != null ? task.realActivity.flattenToString()
                     : task.getTopActivity() != null ? task.getTopActivity().packageName
                     : "unknown";
             taskBounds[i] = new Rect();
             task.getWindowContainerBounds(taskBounds[i]);
-            taskUserIds[i] = task.userId;
+            taskUserIds[i] = task.mUserId;
         }
         info.taskIds = taskIds;
         info.taskNames = taskNames;
@@ -2097,7 +2103,7 @@
                         // picker for personal files, opened by a work app, should still get locked.
                         if (taskTopActivityIsUser(task, userId)) {
                             mService.getTaskChangeNotificationController().notifyTaskProfileLocked(
-                                    task.taskId, userId);
+                                    task.mTaskId, userId);
                         }
                     }
                 }
diff --git a/services/core/java/com/android/server/wm/RootWindowContainer.java b/services/core/java/com/android/server/wm/RootWindowContainer.java
index 78fcb37..b6a05d1 100644
--- a/services/core/java/com/android/server/wm/RootWindowContainer.java
+++ b/services/core/java/com/android/server/wm/RootWindowContainer.java
@@ -230,7 +230,7 @@
         final DisplayContent existing = getDisplayContent(displayId);
 
         if (existing != null) {
-            existing.mAcitvityDisplay = activityDisplay;
+            existing.mActivityDisplay = activityDisplay;
             existing.initializeDisplayOverrideConfiguration();
             return existing;
         }
@@ -720,7 +720,7 @@
             mUpdateRotation = updateRotationUnchecked();
         }
 
-        if (mWmService.mWaitingForDrawnCallback != null
+        if (!mWmService.mWaitingForDrawnCallbacks.isEmpty()
                 || (mOrientationChangeComplete && !isLayoutNeeded()
                 && !mUpdateRotation)) {
             mWmService.checkDrawnWindowsLocked();
@@ -813,18 +813,18 @@
         final int defaultDw = defaultInfo.logicalWidth;
         final int defaultDh = defaultInfo.logicalHeight;
         if (mWmService.mWatermark != null) {
-            mWmService.mWatermark.positionSurface(defaultDw, defaultDh);
+            mWmService.mWatermark.positionSurface(defaultDw, defaultDh, mDisplayTransaction);
         }
         if (mWmService.mStrictModeFlash != null) {
-            mWmService.mStrictModeFlash.positionSurface(defaultDw, defaultDh);
+            mWmService.mStrictModeFlash.positionSurface(defaultDw, defaultDh, mDisplayTransaction);
         }
         if (mWmService.mCircularDisplayMask != null) {
             mWmService.mCircularDisplayMask.positionSurface(defaultDw, defaultDh,
-                    mWmService.getDefaultDisplayRotation());
+                    mWmService.getDefaultDisplayRotation(), mDisplayTransaction);
         }
         if (mWmService.mEmulatorDisplayOverlay != null) {
             mWmService.mEmulatorDisplayOverlay.positionSurface(defaultDw, defaultDh,
-                    mWmService.getDefaultDisplayRotation());
+                    mWmService.getDefaultDisplayRotation(), mDisplayTransaction);
         }
 
         final int count = mChildren.size();
@@ -1067,7 +1067,7 @@
     void positionChildAt(int position, DisplayContent child, boolean includingParents) {
         super.positionChildAt(position, child, includingParents);
         if (mRootActivityContainer != null) {
-            mRootActivityContainer.onChildPositionChanged(child.mAcitvityDisplay, position);
+            mRootActivityContainer.onChildPositionChanged(child.mActivityDisplay, position);
         }
     }
 
diff --git a/services/core/java/com/android/server/wm/SeamlessRotator.java b/services/core/java/com/android/server/wm/SeamlessRotator.java
index bcd90a1..ba31818 100644
--- a/services/core/java/com/android/server/wm/SeamlessRotator.java
+++ b/services/core/java/com/android/server/wm/SeamlessRotator.java
@@ -20,9 +20,10 @@
 import static android.view.Surface.ROTATION_90;
 
 import android.graphics.Matrix;
+import android.os.IBinder;
 import android.view.DisplayInfo;
-import android.view.Surface;
 import android.view.Surface.Rotation;
+import android.view.SurfaceControl;
 import android.view.SurfaceControl.Transaction;
 
 import com.android.server.wm.utils.CoordinateTransforms;
@@ -35,7 +36,7 @@
  *
  * Works by transforming the {@link WindowState} back into the old display rotation.
  *
- * Uses {@link android.view.SurfaceControl#deferTransactionUntil(Surface, long)} instead of
+ * Uses {@link Transaction#deferTransactionUntil(SurfaceControl, IBinder, long)} instead of
  * latching on the buffer size to allow for seamless 180 degree rotations.
  */
 public class SeamlessRotator {
diff --git a/services/core/java/com/android/server/wm/StrictModeFlash.java b/services/core/java/com/android/server/wm/StrictModeFlash.java
index 9e5d9ca..f537005 100644
--- a/services/core/java/com/android/server/wm/StrictModeFlash.java
+++ b/services/core/java/com/android/server/wm/StrictModeFlash.java
@@ -39,7 +39,8 @@
     private boolean mDrawNeeded;
     private final int mThickness = 20;
 
-    StrictModeFlash(Supplier<Surface> surfaceFactory, DisplayContent dc) {
+    StrictModeFlash(Supplier<Surface> surfaceFactory, DisplayContent dc,
+            SurfaceControl.Transaction t) {
         mSurface = surfaceFactory.get();
         SurfaceControl ctrl = null;
         try {
@@ -48,9 +49,11 @@
                     .setBufferSize(1, 1)
                     .setFormat(PixelFormat.TRANSLUCENT)
                     .build();
-            ctrl.setLayer(WindowManagerService.TYPE_LAYER_MULTIPLIER * 101);  // one more than Watermark? arbitrary.
-            ctrl.setPosition(0, 0);
-            ctrl.show();
+
+            // one more than Watermark? arbitrary.
+            t.setLayer(ctrl, WindowManagerService.TYPE_LAYER_MULTIPLIER * 101);
+            t.setPosition(ctrl, 0, 0);
+            t.show(ctrl);
             mSurface.copyFrom(ctrl);
         } catch (OutOfResourcesException e) {
         }
@@ -103,25 +106,25 @@
 
     // Note: caller responsible for being inside
     // Surface.openTransaction() / closeTransaction()
-    public void setVisibility(boolean on) {
+    public void setVisibility(boolean on, SurfaceControl.Transaction t) {
         if (mSurfaceControl == null) {
             return;
         }
         drawIfNeeded();
         if (on) {
-            mSurfaceControl.show();
+            t.show(mSurfaceControl);
         } else {
-            mSurfaceControl.hide();
+            t.hide(mSurfaceControl);
         }
     }
 
-    void positionSurface(int dw, int dh) {
+    void positionSurface(int dw, int dh, SurfaceControl.Transaction t) {
         if (mLastDW == dw && mLastDH == dh) {
             return;
         }
         mLastDW = dw;
         mLastDH = dh;
-        mSurfaceControl.setBufferSize(dw, dh);
+        t.setBufferSize(mSurfaceControl, dw, dh);
         mDrawNeeded = true;
     }
 
diff --git a/services/core/java/com/android/server/wm/Task.java b/services/core/java/com/android/server/wm/Task.java
index 5e14087..a181c18 100644
--- a/services/core/java/com/android/server/wm/Task.java
+++ b/services/core/java/com/android/server/wm/Task.java
@@ -63,7 +63,9 @@
 
     // TODO: Track parent marks like this in WindowContainer.
     TaskStack mStack;
+    /* Unique identifier for this task. */
     final int mTaskId;
+    /* User for which this task was created. */
     final int mUserId;
     private boolean mDeferRemoval = false;
 
@@ -97,6 +99,8 @@
     private boolean mDragResizing;
     private int mDragResizeMode;
 
+    // This represents the last resolved activity values for this task
+    // NOTE: This value needs to be persisted with each task
     private TaskDescription mTaskDescription;
 
     // If set to true, the task will report that it is not in the floating
@@ -114,6 +118,13 @@
     // TODO: remove after unification
     TaskRecord mTaskRecord;
 
+    // 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*/);
+    }
+
     Task(int taskId, TaskStack stack, int userId, WindowManagerService service, int resizeMode,
             boolean supportsPictureInPicture, TaskDescription taskDescription,
             TaskRecord taskRecord) {
@@ -124,16 +135,17 @@
         mResizeMode = resizeMode;
         mSupportsPictureInPicture = supportsPictureInPicture;
         mTaskRecord = taskRecord;
-        if (mTaskRecord != null) {
-            // This can be null when we call createTaskInStack in WindowTestUtils. Remove this after
-            // unification.
-            mTaskRecord.registerConfigurationChangeListener(this);
-        }
-        setBounds(getRequestedOverrideBounds());
         mTaskDescription = taskDescription;
 
         // Tasks have no set orientation value (including SCREEN_ORIENTATION_UNSPECIFIED).
         setOrientation(SCREEN_ORIENTATION_UNSET);
+        if (mTaskRecord != null) {
+            // This can be null when we call createTaskInStack in WindowTestUtils. Remove this after
+            // unification.
+            mTaskRecord.registerConfigurationChangeListener(this);
+        } else {
+            setBounds(getResolvedOverrideBounds());
+        }
     }
 
     @Override
diff --git a/services/core/java/com/android/server/wm/TaskChangeNotificationController.java b/services/core/java/com/android/server/wm/TaskChangeNotificationController.java
index 5e8831d..a61c908 100644
--- a/services/core/java/com/android/server/wm/TaskChangeNotificationController.java
+++ b/services/core/java/com/android/server/wm/TaskChangeNotificationController.java
@@ -58,6 +58,7 @@
     private static final int NOTIFY_TASK_DISPLAY_CHANGED_LISTENERS_MSG = 23;
     private static final int NOTIFY_TASK_LIST_UPDATED_LISTENERS_MSG = 24;
     private static final int NOTIFY_SINGLE_TASK_DISPLAY_EMPTY = 25;
+    private static final int NOTIFY_TASK_LIST_FROZEN_UNFROZEN_MSG = 26;
 
     // Delay in notifying task stack change listeners (in millis)
     private static final int NOTIFY_TASK_STACK_CHANGE_LISTENERS_DELAY = 100;
@@ -174,6 +175,10 @@
         l.onRecentTaskListUpdated();
     };
 
+    private final TaskStackConsumer mNotifyTaskListFrozen = (l, m) -> {
+        l.onRecentTaskListFrozenChanged(m.arg1 != 0);
+    };
+
     @FunctionalInterface
     public interface TaskStackConsumer {
         void accept(ITaskStackListener t, Message m) throws RemoteException;
@@ -265,6 +270,9 @@
                 case NOTIFY_TASK_LIST_UPDATED_LISTENERS_MSG:
                     forAllRemoteListeners(mNotifyTaskListUpdated, msg);
                     break;
+                case NOTIFY_TASK_LIST_FROZEN_UNFROZEN_MSG:
+                    forAllRemoteListeners(mNotifyTaskListFrozen, msg);
+                    break;
             }
         }
     }
@@ -342,7 +350,7 @@
     void notifyActivityPinned(ActivityRecord r) {
         mHandler.removeMessages(NOTIFY_ACTIVITY_PINNED_LISTENERS_MSG);
         final Message msg = mHandler.obtainMessage(NOTIFY_ACTIVITY_PINNED_LISTENERS_MSG,
-                r.getTaskRecord().taskId, r.getStackId(), r.packageName);
+                r.getTaskRecord().mTaskId, r.getStackId(), r.packageName);
         msg.sendingUid = r.mUserId;
         forAllLocalListeners(mNotifyActivityPinned, msg);
         msg.sendToTarget();
@@ -549,4 +557,12 @@
         forAllLocalListeners(mNotifyTaskListUpdated, msg);
         msg.sendToTarget();
     }
+
+    /** @see ITaskStackListener#onRecentTaskListFrozenChanged(boolean) */
+    void notifyTaskListFrozen(boolean frozen) {
+        final Message msg = mHandler.obtainMessage(NOTIFY_TASK_LIST_FROZEN_UNFROZEN_MSG,
+                frozen ? 1 : 0, 0 /* unused */);
+        forAllLocalListeners(mNotifyTaskListFrozen, msg);
+        msg.sendToTarget();
+    }
 }
diff --git a/services/core/java/com/android/server/wm/TaskLaunchParamsModifier.java b/services/core/java/com/android/server/wm/TaskLaunchParamsModifier.java
index 1c015d0..9712277 100644
--- a/services/core/java/com/android/server/wm/TaskLaunchParamsModifier.java
+++ b/services/core/java/com/android/server/wm/TaskLaunchParamsModifier.java
@@ -398,9 +398,11 @@
             return;
         }
 
-        final Rect bounds = display.getBounds();
-        final int defaultWidth = bounds.width();
-        final int defaultHeight = bounds.height();
+        // Use stable frame instead of raw frame to avoid launching freeform windows on top of
+        // stable insets, which usually are system widgets such as sysbar & navbar.
+        final Rect displayStableBounds = display.mDisplayContent.mDisplayFrames.mStable;
+        final int defaultWidth = displayStableBounds.width();
+        final int defaultHeight = displayStableBounds.height();
 
         int width;
         int height;
@@ -451,6 +453,7 @@
         }
 
         outBounds.set(0, 0, width, height);
+        outBounds.offset(displayStableBounds.left, displayStableBounds.top);
         final int xOffset = (int) (fractionOfHorizontalOffset * (defaultWidth - width));
         final int yOffset = (int) (fractionOfVerticalOffset * (defaultHeight - height));
         outBounds.offset(xOffset, yOffset);
@@ -627,10 +630,14 @@
             @NonNull ActivityInfo.WindowLayout layout, int orientation, @NonNull Rect bounds) {
         // Default size, which is letterboxing/pillarboxing in display. That's to say the large
         // dimension of default size is the small dimension of display size, and the small dimension
-        // of default size is calculated to keep the same aspect ratio as the display's.
-        Rect displayBounds = display.getBounds();
-        final int portraitHeight = Math.min(displayBounds.width(), displayBounds.height());
-        final int otherDimension = Math.max(displayBounds.width(), displayBounds.height());
+        // of default size is calculated to keep the same aspect ratio as the display's. Here we use
+        // stable bounds of displays because that indicates the area that isn't occupied by system
+        // widgets (e.g. sysbar and navbar).
+        Rect displayStableBounds = display.mDisplayContent.mDisplayFrames.mStable;
+        final int portraitHeight =
+                Math.min(displayStableBounds.width(), displayStableBounds.height());
+        final int otherDimension =
+                Math.max(displayStableBounds.width(), displayStableBounds.height());
         final int portraitWidth = (portraitHeight * portraitHeight) / otherDimension;
         final int defaultWidth = (orientation == SCREEN_ORIENTATION_LANDSCAPE) ? portraitHeight
                 : portraitWidth;
@@ -656,16 +663,17 @@
         final int height = Math.min(defaultHeight, Math.max(phoneHeight, layoutMinHeight));
 
         bounds.set(0, 0, width, height);
+        bounds.offset(displayStableBounds.left, displayStableBounds.top);
     }
 
     /**
      * Gets centered bounds of width x height. If inOutBounds is not empty, the result bounds
-     * centers at its center or display's center if inOutBounds is empty.
+     * centers at its center or display's app bounds center if inOutBounds is empty.
      */
     private void centerBounds(@NonNull ActivityDisplay display, int width, int height,
             @NonNull Rect inOutBounds) {
         if (inOutBounds.isEmpty()) {
-            display.getBounds(inOutBounds);
+            inOutBounds.set(display.mDisplayContent.mDisplayFrames.mStable);
         }
         final int left = inOutBounds.centerX() - width / 2;
         final int top = inOutBounds.centerY() - height / 2;
@@ -674,40 +682,40 @@
 
     private void adjustBoundsToFitInDisplay(@NonNull ActivityDisplay display,
             @NonNull Rect inOutBounds) {
-        final Rect displayBounds = display.getBounds();
+        final Rect displayStableBounds = display.mDisplayContent.mDisplayFrames.mStable;
 
-        if (displayBounds.width() < inOutBounds.width()
-                || displayBounds.height() < inOutBounds.height()) {
+        if (displayStableBounds.width() < inOutBounds.width()
+                || displayStableBounds.height() < inOutBounds.height()) {
             // There is no way for us to fit the bounds in the display without changing width
             // or height. Just move the start to align with the display.
             final int layoutDirection =
                     mSupervisor.mRootActivityContainer.getConfiguration().getLayoutDirection();
             final int left = layoutDirection == View.LAYOUT_DIRECTION_RTL
-                    ? displayBounds.width() - inOutBounds.width()
-                    : 0;
-            inOutBounds.offsetTo(left, 0 /* newTop */);
+                    ? displayStableBounds.right - inOutBounds.right + inOutBounds.left
+                    : displayStableBounds.left;
+            inOutBounds.offsetTo(left, displayStableBounds.top);
             return;
         }
 
         final int dx;
-        if (inOutBounds.right > displayBounds.right) {
+        if (inOutBounds.right > displayStableBounds.right) {
             // Right edge is out of display.
-            dx = displayBounds.right - inOutBounds.right;
-        } else if (inOutBounds.left < displayBounds.left) {
+            dx = displayStableBounds.right - inOutBounds.right;
+        } else if (inOutBounds.left < displayStableBounds.left) {
             // Left edge is out of display.
-            dx = displayBounds.left - inOutBounds.left;
+            dx = displayStableBounds.left - inOutBounds.left;
         } else {
             // Vertical edges are all in display.
             dx = 0;
         }
 
         final int dy;
-        if (inOutBounds.top < displayBounds.top) {
+        if (inOutBounds.top < displayStableBounds.top) {
             // Top edge is out of display.
-            dy = displayBounds.top - inOutBounds.top;
-        } else if (inOutBounds.bottom > displayBounds.bottom) {
+            dy = displayStableBounds.top - inOutBounds.top;
+        } else if (inOutBounds.bottom > displayStableBounds.bottom) {
             // Bottom edge is out of display.
-            dy = displayBounds.bottom - inOutBounds.bottom;
+            dy = displayStableBounds.bottom - inOutBounds.bottom;
         } else {
             // Horizontal edges are all in display.
             dy = 0;
diff --git a/services/core/java/com/android/server/wm/TaskPersister.java b/services/core/java/com/android/server/wm/TaskPersister.java
index 06bdcc0..f9a75d3 100644
--- a/services/core/java/com/android/server/wm/TaskPersister.java
+++ b/services/core/java/com/android/server/wm/TaskPersister.java
@@ -122,7 +122,7 @@
         mPersisterQueue.removeItems(
                 item -> {
                     File file = new File(item.mFilePath);
-                    return file.getName().startsWith(Integer.toString(task.taskId));
+                    return file.getName().startsWith(Integer.toString(task.mTaskId));
                 },
                 ImageWriteQueueItem.class);
     }
@@ -262,7 +262,7 @@
         }
         for (int taskNdx = tasks.size() - 1; taskNdx >= 0; --taskNdx) {
             final TaskRecord task = tasks.get(taskNdx);
-            if (task.taskId == taskId) {
+            if (task.mTaskId == taskId) {
                 return task;
             }
         }
@@ -329,14 +329,14 @@
                                 // read the same thing again.
                                 // mWriteQueue.add(new TaskWriteQueueItem(task));
 
-                                final int taskId = task.taskId;
+                                final int taskId = task.mTaskId;
                                 if (mService.mRootActivityContainer.anyTaskForId(taskId,
                                         MATCH_TASK_IN_STACKS_OR_RECENT_TASKS) != null) {
                                     // Should not happen.
                                     Slog.wtf(TAG, "Existing task with taskId " + taskId + "found");
-                                } else if (userId != task.userId) {
+                                } else if (userId != task.mUserId) {
                                     // Should not happen.
-                                    Slog.wtf(TAG, "Task with userId " + task.userId + " found in "
+                                    Slog.wtf(TAG, "Task with userId " + task.mUserId + " found in "
                                             + userTasksDir.getAbsolutePath());
                                 } else {
                                     // Looks fine.
@@ -560,14 +560,14 @@
                 FileOutputStream file = null;
                 AtomicFile atomicFile = null;
                 try {
-                    File userTasksDir = getUserTasksDir(task.userId);
+                    File userTasksDir = getUserTasksDir(task.mUserId);
                     if (!userTasksDir.isDirectory() && !userTasksDir.mkdirs()) {
-                        Slog.e(TAG, "Failure creating tasks directory for user " + task.userId
+                        Slog.e(TAG, "Failure creating tasks directory for user " + task.mUserId
                                 + ": " + userTasksDir + " Dropping persistence for task " + task);
                         return;
                     }
                     atomicFile = new AtomicFile(new File(userTasksDir,
-                            String.valueOf(task.taskId) + TASK_FILENAME_SUFFIX));
+                            String.valueOf(task.mTaskId) + TASK_FILENAME_SUFFIX));
                     file = atomicFile.startWrite();
                     file.write(stringWriter.toString().getBytes());
                     file.write('\n');
diff --git a/services/core/java/com/android/server/wm/TaskPositioner.java b/services/core/java/com/android/server/wm/TaskPositioner.java
index b680fa4..478b1b5 100644
--- a/services/core/java/com/android/server/wm/TaskPositioner.java
+++ b/services/core/java/com/android/server/wm/TaskPositioner.java
@@ -256,7 +256,7 @@
         final InputChannel[] channels = InputChannel.openInputChannelPair(TAG);
         mServerChannel = channels[0];
         mClientChannel = channels[1];
-        mService.mInputManager.registerInputChannel(mServerChannel, null);
+        mService.mInputManager.registerInputChannel(mServerChannel);
 
         mInputEventReceiver = new WindowPositionerEventReceiver(
                 mClientChannel, mService.mAnimationHandler.getLooper(),
@@ -267,8 +267,7 @@
         mDragApplicationHandle.dispatchingTimeoutNanos =
                 WindowManagerService.DEFAULT_INPUT_DISPATCHING_TIMEOUT_NANOS;
 
-        mDragWindowHandle = new InputWindowHandle(mDragApplicationHandle, null,
-                display.getDisplayId());
+        mDragWindowHandle = new InputWindowHandle(mDragApplicationHandle, display.getDisplayId());
         mDragWindowHandle.name = TAG;
         mDragWindowHandle.token = mServerChannel.getToken();
         mDragWindowHandle.layer = mService.getDragLayerLocked();
diff --git a/services/core/java/com/android/server/wm/TaskRecord.java b/services/core/java/com/android/server/wm/TaskRecord.java
index 0ea108e..75333c7 100644
--- a/services/core/java/com/android/server/wm/TaskRecord.java
+++ b/services/core/java/com/android/server/wm/TaskRecord.java
@@ -208,7 +208,7 @@
      */
     private static TaskRecordFactory sTaskRecordFactory;
 
-    final int taskId;       // Unique identifier for this task.
+    final int mTaskId;      // Unique identifier for this task.
     String affinity;        // The affinity name for this task, or null; may change identity.
     String rootAffinity;    // Initial base affinity, or null; does not change from initial root.
     final IVoiceInteractionSession voiceSession;    // Voice interaction session driving task
@@ -234,7 +234,7 @@
     boolean hasBeenVisible; // Set if any activities in the task have been visible to the user.
 
     String stringName;      // caching of toString() result.
-    int userId;             // user for which this task was created
+    int mUserId;            // user for which this task was created
     boolean mUserSetupComplete; // The user set-up is complete as of the last time the task activity
                                 // was changed.
 
@@ -262,7 +262,7 @@
 
     // This represents the last resolved activity values for this task
     // NOTE: This value needs to be persisted with each task
-    TaskDescription lastTaskDescription = new TaskDescription();
+    TaskDescription mTaskDescription;
 
     /** List of all activities in the task arranged in history order */
     final ArrayList<ActivityRecord> mActivities;
@@ -282,7 +282,7 @@
     /** Only used for persistable tasks, otherwise 0. The last time this task was moved. Used for
      * determining the order when restoring. Sign indicates whether last task movement was to front
      * (positive) or back (negative). Absolute value indicates time. */
-    long mLastTimeMoved = System.currentTimeMillis();
+    long mLastTimeMoved;
 
     /** If original intent did not allow relinquishing task identity, save that information */
     private boolean mNeverRelinquishIdentity = true;
@@ -304,7 +304,7 @@
     int mCallingUid;
     String mCallingPackage;
 
-    final ActivityTaskManagerService mService;
+    final ActivityTaskManagerService mAtmService;
 
     private final Rect mTmpStableBounds = new Rect();
     private final Rect mTmpNonDecorBounds = new Rect();
@@ -342,60 +342,25 @@
      * Don't use constructor directly. Use {@link #create(ActivityTaskManagerService, int,
      * ActivityInfo, Intent, TaskDescription)} instead.
      */
-    TaskRecord(ActivityTaskManagerService service, int _taskId, ActivityInfo info, Intent _intent,
-            IVoiceInteractionSession _voiceSession, IVoiceInteractor _voiceInteractor) {
-        mService = service;
-        userId = UserHandle.getUserId(info.applicationInfo.uid);
-        taskId = _taskId;
-        lastActiveTime = SystemClock.elapsedRealtime();
-        mAffiliatedTaskId = _taskId;
-        voiceSession = _voiceSession;
-        voiceInteractor = _voiceInteractor;
-        isAvailable = true;
-        mActivities = new ArrayList<>();
-        mCallingUid = info.applicationInfo.uid;
-        mCallingPackage = info.packageName;
-        setIntent(_intent, info);
-        setMinDimensions(info);
-        touchActiveTime();
-        mService.getTaskChangeNotificationController().notifyTaskCreated(_taskId, realActivity);
+    TaskRecord(ActivityTaskManagerService atmService, int _taskId, ActivityInfo info,
+            Intent _intent, IVoiceInteractionSession _voiceSession,
+            IVoiceInteractor _voiceInteractor, TaskDescription _taskDescription) {
+        this(atmService, _taskId, _intent,  null /*_affinityIntent*/, null /*_affinity*/,
+                null /*_rootAffinity*/, null /*_realActivity*/, null /*_origActivity*/,
+                false /*_rootWasReset*/, false /*_autoRemoveRecents*/, false /*_askedCompatMode*/,
+                UserHandle.getUserId(info.applicationInfo.uid), 0 /*_effectiveUid*/,
+                null /*_lastDescription*/, new ArrayList<>(), System.currentTimeMillis(),
+                true /*neverRelinquishIdentity*/,
+                _taskDescription != null ? _taskDescription : new TaskDescription(),
+                _taskId, INVALID_TASK_ID, INVALID_TASK_ID, 0 /*taskAffiliationColor*/,
+                info.applicationInfo.uid, info.packageName, info.resizeMode,
+                info.supportsPictureInPicture(), false /*_realActivitySuspended*/,
+                false /*userSetupComplete*/, INVALID_MIN_SIZE, INVALID_MIN_SIZE, info,
+                _voiceSession, _voiceInteractor);
     }
 
-    /**
-     * Don't use constructor directly.
-     * Use {@link #create(ActivityTaskManagerService, int, ActivityInfo,
-     * Intent, IVoiceInteractionSession, IVoiceInteractor)} instead.
-     */
-    TaskRecord(ActivityTaskManagerService service, int _taskId, ActivityInfo info, Intent _intent,
-            TaskDescription _taskDescription) {
-        mService = service;
-        userId = UserHandle.getUserId(info.applicationInfo.uid);
-        taskId = _taskId;
-        lastActiveTime = SystemClock.elapsedRealtime();
-        mAffiliatedTaskId = _taskId;
-        voiceSession = null;
-        voiceInteractor = null;
-        isAvailable = true;
-        mActivities = new ArrayList<>();
-        mCallingUid = info.applicationInfo.uid;
-        mCallingPackage = info.packageName;
-        setIntent(_intent, info);
-        setMinDimensions(info);
-
-        isPersistable = true;
-        // Clamp to [1, max].
-        maxRecents = Math.min(Math.max(info.maxRecents, 1),
-                ActivityTaskManager.getMaxAppRecentsLimitStatic());
-
-        lastTaskDescription = _taskDescription;
-        touchActiveTime();
-        mService.getTaskChangeNotificationController().notifyTaskCreated(_taskId, realActivity);
-    }
-
-    /**
-     * Don't use constructor directly. This is only used by XML parser.
-     */
-    TaskRecord(ActivityTaskManagerService service, int _taskId, Intent _intent,
+    /** Don't use constructor directly. This is only used by XML parser. */
+    TaskRecord(ActivityTaskManagerService atmService, int _taskId, Intent _intent,
             Intent _affinityIntent, String _affinity, String _rootAffinity,
             ComponentName _realActivity, ComponentName _origActivity, boolean _rootWasReset,
             boolean _autoRemoveRecents, boolean _askedCompatMode, int _userId,
@@ -404,15 +369,15 @@
             TaskDescription _lastTaskDescription, int taskAffiliation, int prevTaskId,
             int nextTaskId, int taskAffiliationColor, int callingUid, String callingPackage,
             int resizeMode, boolean supportsPictureInPicture, boolean _realActivitySuspended,
-            boolean userSetupComplete, int minWidth, int minHeight) {
-        mService = service;
-        taskId = _taskId;
-        intent = _intent;
+            boolean userSetupComplete, int minWidth, int minHeight, ActivityInfo info,
+            IVoiceInteractionSession _voiceSession, IVoiceInteractor _voiceInteractor) {
+        mAtmService = atmService;
+        mTaskId = _taskId;
         affinityIntent = _affinityIntent;
         affinity = _affinity;
         rootAffinity = _rootAffinity;
-        voiceSession = null;
-        voiceInteractor = null;
+        voiceSession = _voiceSession;
+        voiceInteractor = _voiceInteractor;
         realActivity = _realActivity;
         realActivitySuspended = _realActivitySuspended;
         origActivity = _origActivity;
@@ -420,15 +385,15 @@
         isAvailable = true;
         autoRemoveRecents = _autoRemoveRecents;
         askedCompatMode = _askedCompatMode;
-        userId = _userId;
+        mUserId = _userId;
         mUserSetupComplete = userSetupComplete;
         effectiveUid = _effectiveUid;
-        lastActiveTime = SystemClock.elapsedRealtime();
+        touchActiveTime();
         lastDescription = _lastDescription;
         mActivities = activities;
         mLastTimeMoved = lastTimeMoved;
         mNeverRelinquishIdentity = neverRelinquishIdentity;
-        lastTaskDescription = _lastTaskDescription;
+        mTaskDescription = _lastTaskDescription;
         mAffiliatedTaskId = taskAffiliation;
         mAffiliatedTaskColor = taskAffiliationColor;
         mPrevAffiliateTaskId = prevTaskId;
@@ -437,9 +402,15 @@
         mCallingPackage = callingPackage;
         mResizeMode = resizeMode;
         mSupportsPictureInPicture = supportsPictureInPicture;
-        mMinWidth = minWidth;
-        mMinHeight = minHeight;
-        mService.getTaskChangeNotificationController().notifyTaskCreated(_taskId, realActivity);
+        if (info != null) {
+            setIntent(_intent, info);
+            setMinDimensions(info);
+        } else {
+            intent = _intent;
+            mMinWidth = minWidth;
+            mMinHeight = minHeight;
+        }
+        mAtmService.getTaskChangeNotificationController().notifyTaskCreated(_taskId, realActivity);
     }
 
     Task getTask() {
@@ -458,9 +429,9 @@
         if (stack == null) {
             throw new IllegalArgumentException("TaskRecord: invalid stack=" + mStack);
         }
-        EventLog.writeEvent(WM_TASK_CREATED, taskId, stack.mStackId);
-        mTask = new Task(taskId, stack, userId, mService.mWindowManager, mResizeMode,
-                mSupportsPictureInPicture, lastTaskDescription, this);
+        EventLog.writeEvent(WM_TASK_CREATED, mTaskId, stack.mStackId);
+        mTask = new Task(mTaskId, stack, mUserId, mAtmService.mWindowManager, mResizeMode,
+                mSupportsPictureInPicture, mTaskDescription, this);
         final int position = onTop ? POSITION_TOP : POSITION_BOTTOM;
 
         if (!mDisplayedBounds.isEmpty()) {
@@ -487,14 +458,14 @@
         final boolean isVoiceSession = voiceSession != null;
         if (isVoiceSession) {
             try {
-                voiceSession.taskFinished(intent, taskId);
+                voiceSession.taskFinished(intent, mTaskId);
             } catch (RemoteException e) {
             }
         }
         if (autoRemoveFromRecents() || isVoiceSession) {
             // Task creator asked to remove this when done, or this task was a voice
             // interaction, so it should not remain on the recent tasks list.
-            mService.mStackSupervisor.mRecentTasks.remove(this);
+            mAtmService.mStackSupervisor.mRecentTasks.remove(this);
         }
 
         removeWindowContainer();
@@ -502,9 +473,9 @@
 
     @VisibleForTesting
     void removeWindowContainer() {
-        mService.getLockTaskController().clearLockedTask(this);
+        mAtmService.getLockTaskController().clearLockedTask(this);
         if (mTask == null) {
-            if (DEBUG_STACK) Slog.i(TAG_WM, "removeTask: could not find taskId=" + taskId);
+            if (DEBUG_STACK) Slog.i(TAG_WM, "removeTask: could not find taskId=" + mTaskId);
             return;
         }
         mTask.removeIfPossible();
@@ -514,11 +485,11 @@
             // default configuration the next time it launches.
             setBounds(null);
         }
-        mService.getTaskChangeNotificationController().notifyTaskRemoved(taskId);
+        mAtmService.getTaskChangeNotificationController().notifyTaskRemoved(mTaskId);
     }
 
-    public void onSnapshotChanged(TaskSnapshot snapshot) {
-        mService.getTaskChangeNotificationController().notifyTaskSnapshotChanged(taskId, snapshot);
+    void onSnapshotChanged(TaskSnapshot snapshot) {
+        mAtmService.getTaskChangeNotificationController().notifyTaskSnapshotChanged(mTaskId, snapshot);
     }
 
     void setResizeMode(int resizeMode) {
@@ -527,13 +498,13 @@
         }
         mResizeMode = resizeMode;
         mTask.setResizeable(resizeMode);
-        mService.mRootActivityContainer.ensureActivitiesVisible(null, 0, !PRESERVE_WINDOWS);
-        mService.mRootActivityContainer.resumeFocusedStacksTopActivities();
+        mAtmService.mRootActivityContainer.ensureActivitiesVisible(null, 0, !PRESERVE_WINDOWS);
+        mAtmService.mRootActivityContainer.resumeFocusedStacksTopActivities();
     }
 
     void setTaskDockedResizing(boolean resizing) {
         if (mTask == null) {
-            Slog.w(TAG_WM, "setTaskDockedResizing: taskId " + taskId + " not found.");
+            Slog.w(TAG_WM, "setTaskDockedResizing: taskId " + mTaskId + " not found.");
             return;
         }
         mTask.setTaskDockedResizing(resizing);
@@ -541,11 +512,11 @@
 
     // TODO: Consolidate this with the resize() method below.
     public void requestResize(Rect bounds, int resizeMode) {
-        mService.resizeTask(taskId, bounds, resizeMode);
+        mAtmService.resizeTask(mTaskId, bounds, resizeMode);
     }
 
     boolean resize(Rect bounds, int resizeMode, boolean preserveWindow, boolean deferResume) {
-        mService.deferWindowLayout();
+        mAtmService.deferWindowLayout();
 
         try {
             if (!isResizeable()) {
@@ -568,7 +539,7 @@
                 setBounds(bounds);
                 if (!inFreeformWindowingMode()) {
                     // re-restore the task so it can have the proper stack association.
-                    mService.mStackSupervisor.restoreRecentTaskLocked(this, null, !ON_TOP);
+                    mAtmService.mStackSupervisor.restoreRecentTaskLocked(this, null, !ON_TOP);
                 }
                 return true;
             }
@@ -582,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_" + taskId);
+            Trace.traceBegin(TRACE_TAG_ACTIVITY_MANAGER, "am.resizeTask_" + mTaskId);
 
             boolean updatedConfig = false;
             mTmpConfig.setTo(getResolvedOverrideConfiguration());
@@ -606,9 +577,9 @@
                     // this won't cause tons of irrelevant windows being preserved because only
                     // activities in this task may experience a bounds change. Configs for other
                     // activities stay the same.
-                    mService.mRootActivityContainer.ensureActivitiesVisible(r, 0, preserveWindow);
+                    mAtmService.mRootActivityContainer.ensureActivitiesVisible(r, 0, preserveWindow);
                     if (!kept) {
-                        mService.mRootActivityContainer.resumeFocusedStacksTopActivities();
+                        mAtmService.mRootActivityContainer.resumeFocusedStacksTopActivities();
                     }
                 }
             }
@@ -619,7 +590,7 @@
             Trace.traceEnd(TRACE_TAG_ACTIVITY_MANAGER);
             return kept;
         } finally {
-            mService.continueWindowLayout();
+            mAtmService.continueWindowLayout();
         }
     }
 
@@ -687,9 +658,9 @@
     boolean reparent(ActivityStack preferredStack, int position,
             @ReparentMoveStackMode int moveStackMode, boolean animate, boolean deferResume,
             boolean schedulePictureInPictureModeChange, String reason) {
-        final ActivityStackSupervisor supervisor = mService.mStackSupervisor;
-        final RootActivityContainer root = mService.mRootActivityContainer;
-        final WindowManagerService windowManager = mService.mWindowManager;
+        final ActivityStackSupervisor supervisor = mAtmService.mStackSupervisor;
+        final RootActivityContainer root = mAtmService.mRootActivityContainer;
+        final WindowManagerService windowManager = mAtmService.mWindowManager;
         final ActivityStack sourceStack = getStack();
         final ActivityStack toStack = supervisor.getReparentTargetStack(this, preferredStack,
                 position == MAX_VALUE);
@@ -725,7 +696,7 @@
             windowManager.setWillReplaceWindow(topActivity.appToken, animate);
         }
 
-        mService.deferWindowLayout();
+        mAtmService.deferWindowLayout();
         boolean kept = true;
         try {
             final ActivityRecord r = topRunningActivityLocked();
@@ -764,7 +735,7 @@
             // Notify the voice session if required
             if (voiceSession != null) {
                 try {
-                    voiceSession.taskStarted(intent, taskId);
+                    voiceSession.taskStarted(intent, mTaskId);
                 } catch (RemoteException e) {
                 }
             }
@@ -776,7 +747,7 @@
                         wasPaused, reason);
             }
             if (!animate) {
-                mService.mStackSupervisor.mNoAnimActivities.add(topActivity);
+                mAtmService.mStackSupervisor.mNoAnimActivities.add(topActivity);
             }
 
             // We might trigger a configuration change. Save the current task bounds for freezing.
@@ -795,7 +766,7 @@
             } else if (toStackWindowingMode == WINDOWING_MODE_FREEFORM) {
                 Rect bounds = getLaunchBounds();
                 if (bounds == null) {
-                    mService.mStackSupervisor.getLaunchParamsController().layoutTask(this, null);
+                    mAtmService.mStackSupervisor.getLaunchParamsController().layoutTask(this, null);
                     bounds = configBounds;
                 }
                 kept = resize(bounds, RESIZE_MODE_FORCED, !mightReplaceWindow, deferResume);
@@ -803,13 +774,13 @@
                 if (toStackSplitScreenPrimary && moveStackMode == REPARENT_KEEP_STACK_AT_FRONT) {
                     // Move recents to front so it is not behind home stack when going into docked
                     // mode
-                    mService.mStackSupervisor.moveRecentsStackToFront(reason);
+                    mAtmService.mStackSupervisor.moveRecentsStackToFront(reason);
                 }
                 kept = resize(toStack.getRequestedOverrideBounds(), RESIZE_MODE_SYSTEM,
                         !mightReplaceWindow, deferResume);
             }
         } finally {
-            mService.continueWindowLayout();
+            mAtmService.continueWindowLayout();
         }
 
         if (mightReplaceWindow) {
@@ -846,7 +817,7 @@
 
     void cancelWindowTransition() {
         if (mTask == null) {
-            Slog.w(TAG_WM, "cancelWindowTransition: taskId " + taskId + " not found.");
+            Slog.w(TAG_WM, "cancelWindowTransition: taskId " + mTaskId + " not found.");
             return;
         }
         mTask.cancelTaskWindowTransition();
@@ -859,7 +830,7 @@
 
         // TODO: Move this to {@link TaskWindowContainerController} once recent tasks are more
         // synchronized between AM and WM.
-        return mService.mWindowManager.getTaskSnapshot(taskId, userId, reducedResolution,
+        return mAtmService.mWindowManager.getTaskSnapshot(mTaskId, mUserId, reducedResolution,
                 restoreFromDisk);
     }
 
@@ -938,9 +909,9 @@
             // task as having a true root activity.
             rootWasReset = true;
         }
-        userId = UserHandle.getUserId(info.applicationInfo.uid);
-        mUserSetupComplete = Settings.Secure.getIntForUser(mService.mContext.getContentResolver(),
-                USER_SETUP_COMPLETE, 0, userId) != 0;
+        mUserId = UserHandle.getUserId(info.applicationInfo.uid);
+        mUserSetupComplete = Settings.Secure.getIntForUser(
+                mAtmService.mContext.getContentResolver(), USER_SETUP_COMPLETE, 0, mUserId) != 0;
         if ((info.flags & ActivityInfo.FLAG_AUTO_REMOVE_FROM_RECENTS) != 0) {
             // If the activity itself has requested auto-remove, then just always do it.
             autoRemoveRecents = true;
@@ -993,12 +964,12 @@
 
     void setPrevAffiliate(TaskRecord prevAffiliate) {
         mPrevAffiliate = prevAffiliate;
-        mPrevAffiliateTaskId = prevAffiliate == null ? INVALID_TASK_ID : prevAffiliate.taskId;
+        mPrevAffiliateTaskId = prevAffiliate == null ? INVALID_TASK_ID : prevAffiliate.mTaskId;
     }
 
     void setNextAffiliate(TaskRecord nextAffiliate) {
         mNextAffiliate = nextAffiliate;
-        mNextAffiliateTaskId = nextAffiliate == null ? INVALID_TASK_ID : nextAffiliate.taskId;
+        mNextAffiliateTaskId = nextAffiliate == null ? INVALID_TASK_ID : nextAffiliate.mTaskId;
     }
 
     <T extends ActivityStack> T getStack() {
@@ -1061,7 +1032,7 @@
     @Override
     protected void onParentChanged() {
         super.onParentChanged();
-        mService.mRootActivityContainer.updateUIDsPresentOnDisplay();
+        mAtmService.mRootActivityContainer.updateUIDsPresentOnDisplay();
     }
 
     // Close up recents linked list.
@@ -1080,13 +1051,13 @@
         closeRecentsChain();
         if (inRecents) {
             inRecents = false;
-            mService.notifyTaskPersisterLocked(this, false);
+            mAtmService.notifyTaskPersisterLocked(this, false);
         }
 
         clearRootProcess();
 
-        mService.mWindowManager.mTaskSnapshotController.notifyTaskRemovedFromRecents(
-                taskId, userId);
+        mAtmService.mWindowManager.mTaskSnapshotController.notifyTaskRemovedFromRecents(
+                mTaskId, mUserId);
     }
 
     void setTaskToAffiliateWith(TaskRecord taskToAffiliateWith) {
@@ -1235,7 +1206,7 @@
     boolean okToShowLocked() {
         // NOTE: If {@link TaskRecord#topRunningActivity} return is not null then it is
         // okay to show the activity when locked.
-        return mService.mStackSupervisor.isCurrentProfileLocked(userId)
+        return mAtmService.mStackSupervisor.isCurrentProfileLocked(mUserId)
                 || topRunningActivityLocked() != null;
     }
 
@@ -1251,7 +1222,7 @@
         mActivities.add(newTop);
 
         // Make sure window manager is aware of the position change.
-        mTask.positionChildAtTop(newTop.mAppWindowToken);
+        mTask.positionChildAtTop(newTop);
         updateEffectiveIntent();
     }
 
@@ -1283,7 +1254,7 @@
         r.setTask(this);
 
         // Remove r first, and if it wasn't already in the list and it's fullscreen, count it.
-        if (!mActivities.remove(r) && r.fullscreen) {
+        if (!mActivities.remove(r) && r.occludesParent()) {
             // Was not previously in list.
             numFullscreen++;
         }
@@ -1324,18 +1295,18 @@
 
         updateEffectiveIntent();
         if (r.isPersistable()) {
-            mService.notifyTaskPersisterLocked(this, false);
+            mAtmService.notifyTaskPersisterLocked(this, false);
         }
 
-        if (r.mAppWindowToken != null) {
+        if (r.getParent() != null) {
             // Only attempt to move in WM if the child has a controller. It is possible we haven't
             // created controller for the activity we are starting yet.
-            mTask.positionChildAt(r.mAppWindowToken, index);
+            mTask.positionChildAt(r, index);
         }
 
         // Make sure the list of display UID whitelists is updated
         // now that this record is in a new task.
-        mService.mRootActivityContainer.updateUIDsPresentOnDisplay();
+        mAtmService.mRootActivityContainer.updateUIDsPresentOnDisplay();
     }
 
     /**
@@ -1355,19 +1326,19 @@
 
         r.setTask(null /* task */, reparenting /* reparenting */);
 
-        if (mActivities.remove(r) && r.fullscreen) {
+        if (mActivities.remove(r) && r.occludesParent()) {
             // Was previously in list.
             numFullscreen--;
         }
         if (r.isPersistable()) {
-            mService.notifyTaskPersisterLocked(this, false);
+            mAtmService.notifyTaskPersisterLocked(this, false);
         }
 
         if (inPinnedWindowingMode()) {
             // We normally notify listeners of task stack changes on pause, however pinned stack
             // activities are normally in the paused state so no notification will be sent there
             // before the activity is removed. We send it here so instead.
-            mService.getTaskChangeNotificationController().notifyTaskStackChanged();
+            mAtmService.getTaskChangeNotificationController().notifyTaskStackChanged();
         }
 
         if (mActivities.isEmpty()) {
@@ -1530,10 +1501,10 @@
         }
 
         final String pkg = (realActivity != null) ? realActivity.getPackageName() : null;
-        final LockTaskController lockTaskController = mService.getLockTaskController();
+        final LockTaskController lockTaskController = mAtmService.getLockTaskController();
         switch (r.lockTaskLaunchMode) {
             case LOCK_TASK_LAUNCH_MODE_DEFAULT:
-                mLockTaskAuth = lockTaskController.isPackageWhitelisted(userId, pkg)
+                mLockTaskAuth = lockTaskController.isPackageWhitelisted(mUserId, pkg)
                         ? LOCK_TASK_AUTH_WHITELISTED : LOCK_TASK_AUTH_PINNABLE;
                 break;
 
@@ -1546,7 +1517,7 @@
                 break;
 
             case LOCK_TASK_LAUNCH_MODE_IF_WHITELISTED:
-                mLockTaskAuth = lockTaskController.isPackageWhitelisted(userId, pkg)
+                mLockTaskAuth = lockTaskController.isPackageWhitelisted(mUserId, pkg)
                         ? LOCK_TASK_AUTH_LAUNCHABLE : LOCK_TASK_AUTH_PINNABLE;
                 break;
         }
@@ -1555,7 +1526,7 @@
     }
 
     private boolean isResizeable(boolean checkSupportsPip) {
-        return (mService.mForceResizableActivities || ActivityInfo.isResizeableMode(mResizeMode)
+        return (mAtmService.mForceResizableActivities || ActivityInfo.isResizeableMode(mResizeMode)
                 || (checkSupportsPip && mSupportsPictureInPicture));
     }
 
@@ -1568,8 +1539,8 @@
         // A task can not be docked even if it is considered resizeable because it only supports
         // picture-in-picture mode but has a non-resizeable resizeMode
         return super.supportsSplitScreenWindowingMode()
-                && mService.mSupportsSplitScreenMultiWindow
-                && (mService.mForceResizableActivities
+                && mAtmService.mSupportsSplitScreenMultiWindow
+                && (mAtmService.mForceResizableActivities
                         || (isResizeable(false /* checkSupportsPip */)
                                 && !ActivityInfo.isPreserveOrientationMode(mResizeMode)));
     }
@@ -1582,7 +1553,7 @@
      *         secondary display.
      */
     boolean canBeLaunchedOnDisplay(int displayId) {
-        return mService.mStackSupervisor.canPlaceEntityOnDisplay(displayId,
+        return mAtmService.mStackSupervisor.canPlaceEntityOnDisplay(displayId,
                 -1 /* don't check PID */, -1 /* don't check UID */, null /* activityInfo */);
     }
 
@@ -1700,15 +1671,15 @@
                 }
                 topActivity = false;
             }
-            lastTaskDescription = new TaskDescription(label, null, iconResource, iconFilename,
+            mTaskDescription = new TaskDescription(label, null, iconResource, iconFilename,
                     colorPrimary, colorBackground, statusBarColor, navigationBarColor,
                     statusBarContrastWhenTransparent, navigationBarContrastWhenTransparent);
             if (mTask != null) {
-                mTask.setTaskDescription(lastTaskDescription);
+                mTask.setTaskDescription(mTaskDescription);
             }
             // Update the task affiliation color if we are the parent of the group
-            if (taskId == mAffiliatedTaskId) {
-                mAffiliatedTaskColor = lastTaskDescription.getPrimaryColor();
+            if (mTaskId == mAffiliatedTaskId) {
+                mAffiliatedTaskColor = mTaskDescription.getPrimaryColor();
             }
         }
     }
@@ -1767,9 +1738,9 @@
         // to do this for the pinned stack as the bounds are controlled by the system.
         if (!inPinnedWindowingMode() && mStack != null) {
             final int defaultMinSizeDp =
-                    mService.mRootActivityContainer.mDefaultMinSizeOfResizeableTaskDp;
+                    mAtmService.mRootActivityContainer.mDefaultMinSizeOfResizeableTaskDp;
             final ActivityDisplay display =
-                    mService.mRootActivityContainer.getActivityDisplay(mStack.mDisplayId);
+                    mAtmService.mRootActivityContainer.getActivityDisplay(mStack.mDisplayId);
             final float density =
                     (float) display.getConfiguration().densityDpi / DisplayMetrics.DENSITY_DEFAULT;
             final int defaultMinSize = (int) (defaultMinSizeDp * density);
@@ -1849,7 +1820,7 @@
         final boolean wasInMultiWindowMode = inMultiWindowMode();
         super.onConfigurationChanged(newParentConfig);
         if (wasInMultiWindowMode != inMultiWindowMode()) {
-            mService.mStackSupervisor.scheduleUpdateMultiWindowMode(this);
+            mAtmService.mStackSupervisor.scheduleUpdateMultiWindowMode(this);
         }
 
         // If the configuration supports persistent bounds (eg. Freeform), keep track of the
@@ -1890,7 +1861,7 @@
         }
 
         // Saves the new state so that we can launch the activity at the same location.
-        mService.mStackSupervisor.mLaunchParamsPersister.saveTask(this);
+        mAtmService.mStackSupervisor.mLaunchParamsPersister.saveTask(this);
     }
 
     /**
@@ -2293,7 +2264,7 @@
             if (mLastNonFullscreenBounds != null) {
                 setBounds(mLastNonFullscreenBounds);
             } else {
-                mService.mStackSupervisor.getLaunchParamsController().layoutTask(this, null);
+                mAtmService.mStackSupervisor.getLaunchParamsController().layoutTask(this, null);
             }
         } else {
             setBounds(inStack.getRequestedOverrideBounds());
@@ -2354,9 +2325,9 @@
      */
     void fillTaskInfo(TaskInfo info) {
         getNumRunningActivities(mReuseActivitiesReport);
-        info.userId = userId;
+        info.userId = mUserId;
         info.stackId = getStackId();
-        info.taskId = taskId;
+        info.taskId = mTaskId;
         info.displayId = mStack == null ? Display.INVALID_DISPLAY : mStack.mDisplayId;
         info.isRunning = getTopActivity() != null;
         info.baseIntent = new Intent(getBaseIntent());
@@ -2370,7 +2341,7 @@
         info.realActivity = realActivity;
         info.numActivities = mReuseActivitiesReport.numActivities;
         info.lastActiveTime = lastActiveTime;
-        info.taskDescription = new ActivityManager.TaskDescription(lastTaskDescription);
+        info.taskDescription = new ActivityManager.TaskDescription(mTaskDescription);
         info.supportsSplitScreenMultiWindow = supportsSplitScreenWindowingMode();
         info.resizeMode = mResizeMode;
         info.configuration.setTo(getConfiguration());
@@ -2386,7 +2357,7 @@
     }
 
     void dump(PrintWriter pw, String prefix) {
-        pw.print(prefix); pw.print("userId="); pw.print(userId);
+        pw.print(prefix); pw.print("userId="); pw.print(mUserId);
                 pw.print(" effectiveUid="); UserHandle.formatUid(pw, effectiveUid);
                 pw.print(" mCallingUid="); UserHandle.formatUid(pw, mCallingUid);
                 pw.print(" mUserSetupComplete="); pw.print(mUserSetupComplete);
@@ -2440,7 +2411,7 @@
                     pw.print(" mReuseTask="); pw.print(mReuseTask);
                     pw.print(" mLockTaskAuth="); pw.println(lockTaskAuthToString());
         }
-        if (mAffiliatedTaskId != taskId || mPrevAffiliateTaskId != INVALID_TASK_ID
+        if (mAffiliatedTaskId != mTaskId || mPrevAffiliateTaskId != INVALID_TASK_ID
                 || mPrevAffiliate != null || mNextAffiliateTaskId != INVALID_TASK_ID
                 || mNextAffiliate != null) {
             pw.print(prefix); pw.print("affiliation="); pw.print(mAffiliatedTaskId);
@@ -2487,7 +2458,7 @@
         if (stringName != null) {
             sb.append(stringName);
             sb.append(" U=");
-            sb.append(userId);
+            sb.append(mUserId);
             sb.append(" StackId=");
             sb.append(getStackId());
             sb.append(" sz=");
@@ -2498,7 +2469,7 @@
         sb.append("TaskRecord{");
         sb.append(Integer.toHexString(System.identityHashCode(this)));
         sb.append(" #");
-        sb.append(taskId);
+        sb.append(mTaskId);
         if (affinity != null) {
             sb.append(" A=");
             sb.append(affinity);
@@ -2523,7 +2494,7 @@
 
         final long token = proto.start(fieldId);
         super.writeToProto(proto, CONFIGURATION_CONTAINER, logLevel);
-        proto.write(ID, taskId);
+        proto.write(ID, mTaskId);
         for (int i = mActivities.size() - 1; i >= 0; i--) {
             ActivityRecord activity = mActivities.get(i);
             activity.writeToProto(proto, ACTIVITIES);
@@ -2573,7 +2544,7 @@
     void saveToXml(XmlSerializer out) throws IOException, XmlPullParserException {
         if (DEBUG_RECENTS) Slog.i(TAG_RECENTS, "Saving task=" + this);
 
-        out.attribute(null, ATTR_TASKID, String.valueOf(taskId));
+        out.attribute(null, ATTR_TASKID, String.valueOf(mTaskId));
         if (realActivity != null) {
             out.attribute(null, ATTR_REALACTIVITY, realActivity.flattenToShortString());
         }
@@ -2596,7 +2567,7 @@
         out.attribute(null, ATTR_ROOTHASRESET, String.valueOf(rootWasReset));
         out.attribute(null, ATTR_AUTOREMOVERECENTS, String.valueOf(autoRemoveRecents));
         out.attribute(null, ATTR_ASKEDCOMPATMODE, String.valueOf(askedCompatMode));
-        out.attribute(null, ATTR_USERID, String.valueOf(userId));
+        out.attribute(null, ATTR_USERID, String.valueOf(mUserId));
         out.attribute(null, ATTR_USER_SETUP_COMPLETE, String.valueOf(mUserSetupComplete));
         out.attribute(null, ATTR_EFFECTIVE_UID, String.valueOf(effectiveUid));
         out.attribute(null, ATTR_LASTTIMEMOVED, String.valueOf(mLastTimeMoved));
@@ -2604,8 +2575,8 @@
         if (lastDescription != null) {
             out.attribute(null, ATTR_LASTDESCRIPTION, lastDescription.toString());
         }
-        if (lastTaskDescription != null) {
-            lastTaskDescription.saveToXml(out);
+        if (mTaskDescription != null) {
+            mTaskDescription.saveToXml(out);
         }
         out.attribute(null, ATTR_TASK_AFFILIATION_COLOR, String.valueOf(mAffiliatedTaskColor));
         out.attribute(null, ATTR_TASK_AFFILIATION, String.valueOf(mAffiliatedTaskId));
@@ -2692,13 +2663,14 @@
         TaskRecord create(ActivityTaskManagerService service, int taskId, ActivityInfo info,
                 Intent intent, IVoiceInteractionSession voiceSession,
                 IVoiceInteractor voiceInteractor) {
-            return new TaskRecord(
-                    service, taskId, info, intent, voiceSession, voiceInteractor);
+            return new TaskRecord(service, taskId, info, intent, voiceSession, voiceInteractor,
+                    null /*taskDescription*/);
         }
 
         TaskRecord create(ActivityTaskManagerService service, int taskId, ActivityInfo info,
                 Intent intent, TaskDescription taskDescription) {
-            return new TaskRecord(service, taskId, info, intent, taskDescription);
+            return new TaskRecord(service, taskId, info, intent, null /*voiceSession*/,
+                    null /*voiceInteractor*/, taskDescription);
         }
 
         /**
@@ -2720,7 +2692,8 @@
                     lastTimeMoved, neverRelinquishIdentity, lastTaskDescription, taskAffiliation,
                     prevTaskId, nextTaskId, taskAffiliationColor, callingUid, callingPackage,
                     resizeMode, supportsPictureInPicture, realActivitySuspended, userSetupComplete,
-                    minWidth, minHeight);
+                    minWidth, minHeight, null /*ActivityInfo*/, null /*_voiceSession*/,
+                    null /*_voiceInteractor*/);
         }
 
         TaskRecord restoreFromXml(XmlPullParser in, ActivityStackSupervisor stackSupervisor)
diff --git a/services/core/java/com/android/server/wm/TaskSnapshotSurface.java b/services/core/java/com/android/server/wm/TaskSnapshotSurface.java
index d070850..172ebce 100644
--- a/services/core/java/com/android/server/wm/TaskSnapshotSurface.java
+++ b/services/core/java/com/android/server/wm/TaskSnapshotSurface.java
@@ -134,6 +134,7 @@
     private final int mStatusBarColor;
     @VisibleForTesting final SystemBarBackgroundPainter mSystemBarBackgroundPainter;
     private final int mOrientationOnCreation;
+    private final SurfaceControl.Transaction mTransaction;
 
     static TaskSnapshotSurface create(WindowManagerService service, AppWindowToken token,
             TaskSnapshot snapshot) {
@@ -252,6 +253,7 @@
                 windowPrivateFlags, sysUiVis, taskDescription, 1f);
         mStatusBarColor = taskDescription.getStatusBarColor();
         mOrientationOnCreation = currentOrientation;
+        mTransaction = mService.mTransactionFactory.get();
     }
 
     @Override
@@ -336,27 +338,23 @@
         surface.copyFrom(mChildSurfaceControl);
 
         final Rect frame;
-        SurfaceControl.openTransaction();
-        try {
-            // We can just show the surface here as it will still be hidden as the parent is
-            // still hidden.
-            mChildSurfaceControl.show();
-            if (aspectRatioMismatch) {
-                // Clip off ugly navigation bar.
-                final Rect crop = calculateSnapshotCrop();
-                frame = calculateSnapshotFrame(crop);
-                mChildSurfaceControl.setWindowCrop(crop);
-                mChildSurfaceControl.setPosition(frame.left, frame.top);
-            } else {
-                frame = null;
-            }
-
-            // Scale the mismatch dimensions to fill the task bounds
-            final float scale = 1 / mSnapshot.getScale();
-            mChildSurfaceControl.setMatrix(scale, 0, 0, scale);
-        } finally {
-            SurfaceControl.closeTransaction();
+        // We can just show the surface here as it will still be hidden as the parent is
+        // still hidden.
+        mTransaction.show(mChildSurfaceControl);
+        if (aspectRatioMismatch) {
+            // Clip off ugly navigation bar.
+            final Rect crop = calculateSnapshotCrop();
+            frame = calculateSnapshotFrame(crop);
+            mTransaction.setWindowCrop(mChildSurfaceControl, crop);
+            mTransaction.setPosition(mChildSurfaceControl, frame.left, frame.top);
+        } else {
+            frame = null;
         }
+
+        // Scale the mismatch dimensions to fill the task bounds
+        final float scale = 1 / mSnapshot.getScale();
+        mTransaction.setMatrix(mChildSurfaceControl, scale, 0, 0, scale);
+        mTransaction.apply();
         surface.attachAndQueueBufferWithColorSpace(buffer, mSnapshot.getColorSpace());
         surface.release();
 
diff --git a/services/core/java/com/android/server/wm/Watermark.java b/services/core/java/com/android/server/wm/Watermark.java
index 729cfc0..725aaa48 100644
--- a/services/core/java/com/android/server/wm/Watermark.java
+++ b/services/core/java/com/android/server/wm/Watermark.java
@@ -55,7 +55,7 @@
     private boolean mDrawNeeded;
 
     Watermark(Supplier<Surface> surfaceFactory, DisplayContent dc, DisplayMetrics dm,
-            String[] tokens) {
+            String[] tokens, SurfaceControl.Transaction t) {
         if (false) {
             Log.i(TAG_WM, "*********************** WATERMARK");
             for (int i=0; i<tokens.length; i++) {
@@ -121,21 +121,21 @@
                     .setBufferSize(1, 1)
                     .setFormat(PixelFormat.TRANSLUCENT)
                     .build();
-            ctrl.setLayerStack(mDisplay.getLayerStack());
-            ctrl.setLayer(WindowManagerService.TYPE_LAYER_MULTIPLIER*100);
-            ctrl.setPosition(0, 0);
-            ctrl.show();
+            t.setLayerStack(ctrl, mDisplay.getLayerStack())
+                    .setLayer(ctrl, WindowManagerService.TYPE_LAYER_MULTIPLIER * 100)
+                    .setPosition(ctrl, 0, 0)
+                    .show(ctrl);
             mSurface.copyFrom(ctrl);
         } catch (OutOfResourcesException e) {
         }
         mSurfaceControl = ctrl;
     }
 
-    void positionSurface(int dw, int dh) {
+    void positionSurface(int dw, int dh, SurfaceControl.Transaction t) {
         if (mLastDW != dw || mLastDH != dh) {
             mLastDW = dw;
             mLastDH = dh;
-            mSurfaceControl.setBufferSize(dw, dh);
+            t.setBufferSize(mSurfaceControl, dw, dh);
             mDrawNeeded = true;
         }
     }
diff --git a/services/core/java/com/android/server/wm/WindowAnimator.java b/services/core/java/com/android/server/wm/WindowAnimator.java
index f437b28..3a1d6e0 100644
--- a/services/core/java/com/android/server/wm/WindowAnimator.java
+++ b/services/core/java/com/android/server/wm/WindowAnimator.java
@@ -161,7 +161,8 @@
                     dc.checkAppWindowsReadyToShow();
                     orAnimating(dc.getDockedDividerController().animate(mCurrentTime));
                     if (accessibilityController != null) {
-                        accessibilityController.drawMagnifiedRegionBorderIfNeededLocked(displayId);
+                        accessibilityController.drawMagnifiedRegionBorderIfNeededLocked(displayId,
+                                mTransaction);
                     }
                 }
 
diff --git a/services/core/java/com/android/server/wm/WindowContainer.java b/services/core/java/com/android/server/wm/WindowContainer.java
index 264efe0..a4ab66a 100644
--- a/services/core/java/com/android/server/wm/WindowContainer.java
+++ b/services/core/java/com/android/server/wm/WindowContainer.java
@@ -19,6 +19,11 @@
 import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_BEHIND;
 import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_UNSET;
 import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED;
+import static android.content.pm.ActivityInfo.isFixedOrientationLandscape;
+import static android.content.pm.ActivityInfo.isFixedOrientationPortrait;
+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.view.SurfaceControl.Transaction;
 
 import static com.android.server.wm.WindowContainerProto.CONFIGURATION_CONTAINER;
@@ -28,14 +33,17 @@
 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_ANIM;
 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.WindowStateAnimator.DRAW_PENDING;
 
 import android.annotation.CallSuper;
 import android.annotation.IntDef;
 import android.annotation.Nullable;
 import android.app.WindowConfiguration;
+import android.content.pm.ActivityInfo;
 import android.content.res.Configuration;
 import android.graphics.Point;
 import android.graphics.Rect;
+import android.os.Debug;
 import android.os.IBinder;
 import android.util.Pools;
 import android.util.Slog;
@@ -47,9 +55,11 @@
 
 import com.android.internal.annotations.VisibleForTesting;
 import com.android.internal.util.ToBooleanFunction;
+import com.android.server.policy.WindowManagerPolicy;
 import com.android.server.wm.SurfaceAnimator.Animatable;
 
 import java.io.PrintWriter;
+import java.util.ArrayList;
 import java.util.Comparator;
 import java.util.LinkedList;
 import java.util.function.Consumer;
@@ -117,6 +127,11 @@
     private final Transaction mPendingTransaction;
 
     /**
+     * Windows that clients are waiting to have drawn.
+     */
+    final ArrayList<WindowState> mWaitingForDrawn = new ArrayList<>();
+
+    /**
      * Applied as part of the animation pass in "prepareSurfaces".
      */
     protected final SurfaceAnimator mSurfaceAnimator;
@@ -134,6 +149,8 @@
      */
     private boolean mCommittedReparentToAnimationLeash;
 
+    private final Configuration mTmpConfig = new Configuration();
+
     /**
      * Callback which is triggered while changing the parent, after setting up the surface but
      * before asking the parent to assign child layers.
@@ -260,7 +277,8 @@
         if (child.getParent() != null) {
             throw new IllegalArgumentException("addChild: container=" + child.getName()
                     + " is already a child of container=" + child.getParent().getName()
-                    + " can't add to container=" + getName());
+                    + " can't add to container=" + getName()
+                    + "\n callers=" + Debug.getCallers(15, "\n"));
         }
 
         if ((index < 0 && index != POSITION_BOTTOM)
@@ -751,6 +769,31 @@
     }
 
     /**
+     * Get the configuration orientation by the requested screen orientation
+     * ({@link ActivityInfo.ScreenOrientation}) of this activity.
+     *
+     * @return orientation in ({@link Configuration#ORIENTATION_LANDSCAPE},
+     *         {@link Configuration#ORIENTATION_PORTRAIT},
+     *         {@link Configuration#ORIENTATION_UNDEFINED}).
+     */
+    int getRequestedConfigurationOrientation() {
+        if (mOrientation == ActivityInfo.SCREEN_ORIENTATION_NOSENSOR) {
+            // NOSENSOR means the display's "natural" orientation, so return that.
+            if (mDisplayContent != null) {
+                return mDisplayContent.getNaturalOrientation();
+            }
+        } else if (mOrientation == ActivityInfo.SCREEN_ORIENTATION_LOCKED) {
+            // LOCKED means the activity's orientation remains unchanged, so return existing value.
+            return getConfiguration().orientation;
+        } else if (isFixedOrientationLandscape(mOrientation)) {
+            return ORIENTATION_LANDSCAPE;
+        } else if (isFixedOrientationPortrait(mOrientation)) {
+            return ORIENTATION_PORTRAIT;
+        }
+        return ORIENTATION_UNDEFINED;
+    }
+
+    /**
      * Calls {@link #setOrientation(int, IBinder, ActivityRecord)} with {@code null} to the last 2
      * parameters.
      *
@@ -780,6 +823,13 @@
         }
 
         mOrientation = orientation;
+        final int configOrientation = getRequestedConfigurationOrientation();
+        if (getRequestedOverrideConfiguration().orientation != configOrientation) {
+            mTmpConfig.setTo(getRequestedOverrideConfiguration());
+            mTmpConfig.orientation = configOrientation;
+            onRequestedOverrideConfigurationChanged(mTmpConfig);
+        }
+
         final WindowContainer parent = getParent();
         if (parent != null) {
             onDescendantOrientationChanged(freezeDisplayToken, requestingContainer);
@@ -1392,6 +1442,19 @@
         }
     }
 
+    void waitForAllWindowsDrawn() {
+        final WindowManagerPolicy policy = mWmService.mPolicy;
+        forAllWindows(w -> {
+            final boolean keyguard = policy.isKeyguardHostWindow(w.mAttrs);
+            if (w.isVisibleLw() && (w.mAppToken != null || keyguard)) {
+                w.mWinAnimator.mDrawState = DRAW_PENDING;
+                // Force add to mResizingWindows.
+                w.resetLastContentInsets();
+                mWaitingForDrawn.add(w);
+            }
+        }, true /* traverseTopToBottom */);
+    }
+
     Dimmer getDimmer() {
         if (mParent == null) {
             return null;
diff --git a/services/core/java/com/android/server/wm/WindowHashMap.java b/services/core/java/com/android/server/wm/WindowHashMap.java
deleted file mode 100644
index 49bba41..0000000
--- a/services/core/java/com/android/server/wm/WindowHashMap.java
+++ /dev/null
@@ -1,28 +0,0 @@
-/*
- * Copyright (C) 2017 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License
- */
-
-package com.android.server.wm;
-
-import android.os.IBinder;
-
-import java.util.HashMap;
-
-/**
- * Subclass of HashMap such that we can instruct the compiler to boost our thread priority when
- * locking this class. See makefile.
- */
-class WindowHashMap extends HashMap<IBinder, WindowState> {
-}
diff --git a/services/core/java/com/android/server/wm/WindowManagerInternal.java b/services/core/java/com/android/server/wm/WindowManagerInternal.java
index abbd1ab..f4b7672 100644
--- a/services/core/java/com/android/server/wm/WindowManagerInternal.java
+++ b/services/core/java/com/android/server/wm/WindowManagerInternal.java
@@ -313,10 +313,15 @@
     public abstract void showGlobalActions();
 
     /**
-     * Invalidate all visible windows. Then report back on the callback once all windows have
-     * redrawn.
+     * Invalidate all visible windows on a given display, and report back on the callback when all
+     * windows have redrawn.
+     *
+     * @param callback reporting callback to be called when all windows have redrawn.
+     * @param timeout calls the callback anyway after the timeout.
+     * @param displayId waits for the windows on the given display, INVALID_DISPLAY to wait for all
+     *                  windows on all displays.
      */
-    public abstract void waitForAllWindowsDrawn(Runnable callback, long timeout);
+    public abstract void waitForAllWindowsDrawn(Runnable callback, long timeout, int displayId);
 
     /**
      * Overrides the display size.
@@ -502,6 +507,13 @@
     public abstract boolean shouldShowIme(int displayId);
 
     /**
+     * Show IME on imeTargetWindow once IME has finished layout.
+     *
+     * @param imeTargetWindowToken token of the (IME target) window on which IME should be shown.
+     */
+    public abstract void showImePostLayout(IBinder imeTargetWindowToken);
+
+    /**
      * 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 e3d677c..0287270 100644
--- a/services/core/java/com/android/server/wm/WindowManagerService.java
+++ b/services/core/java/com/android/server/wm/WindowManagerService.java
@@ -16,6 +16,7 @@
 
 package com.android.server.wm;
 
+import static android.Manifest.permission.ACCESS_SURFACE_FLINGER;
 import static android.Manifest.permission.CONTROL_REMOTE_APP_TRANSITION_ANIMATIONS;
 import static android.Manifest.permission.INTERNAL_SYSTEM_WINDOW;
 import static android.Manifest.permission.MANAGE_APP_TOKENS;
@@ -289,6 +290,7 @@
 import java.util.Arrays;
 import java.util.Collections;
 import java.util.Date;
+import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
 import java.util.function.Function;
@@ -516,7 +518,10 @@
     final ArraySet<Session> mSessions = new ArraySet<>();
 
     /** Mapping from an IWindow IBinder to the server's Window object. */
-    final WindowHashMap mWindowMap = new WindowHashMap();
+    final HashMap<IBinder, WindowState> mWindowMap = new HashMap<>();
+
+    /** Mapping from an InputWindowHandle token to the server's Window object. */
+    final HashMap<IBinder, WindowState> mInputToWindowMap = new HashMap<>();
 
     /** Global service lock used by the package the owns this service. */
     final WindowManagerGlobalLock mGlobalLock;
@@ -567,13 +572,10 @@
     final ArrayList<WindowState> mForceRemoves = new ArrayList<>();
 
     /**
-     * Windows that clients are waiting to have drawn.
+     * The callbacks to make when the windows all have been drawn for a given
+     * {@link WindowContainer}.
      */
-    ArrayList<WindowState> mWaitingForDrawn = new ArrayList<>();
-    /**
-     * And the callback to make when they've all been drawn.
-     */
-    Runnable mWaitingForDrawnCallback;
+    final HashMap<WindowContainer, Runnable> mWaitingForDrawnCallbacks = new HashMap<>();
 
     /** List of window currently causing non-system overlay windows to be hidden. */
     private ArrayList<WindowState> mHidingNonSystemOverlayWindows = new ArrayList<>();
@@ -974,6 +976,7 @@
             Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER);
         }
     }
+
     /** Listener to notify activity manager about app transitions. */
     final WindowManagerInternal.AppTransitionListener mActivityManagerAppTransitionNotifier
             = new WindowManagerInternal.AppTransitionListener() {
@@ -990,7 +993,13 @@
             if (atoken == null) {
                 return;
             }
-            if (atoken.mLaunchTaskBehind) {
+
+            // While running a recents animation, this will get called early because we show the
+            // recents animation target activity immediately when the animation starts. Defer the
+            // mLaunchTaskBehind updates until recents animation finishes.
+            final boolean isRecentsAnimationTarget = getRecentsAnimationController() != null
+                    && getRecentsAnimationController().isTargetApp(atoken);
+            if (atoken.mLaunchTaskBehind && !isRecentsAnimationTarget) {
                 try {
                     mActivityTaskManager.notifyLaunchTaskBehindComplete(atoken.token);
                 } catch (RemoteException e) {
@@ -998,20 +1007,13 @@
                 atoken.mLaunchTaskBehind = false;
             } else {
                 atoken.updateReportedVisibilityLocked();
-                if (atoken.mEnteringAnimation) {
-                    if (getRecentsAnimationController() != null
-                            && getRecentsAnimationController().isTargetApp(atoken)) {
-                        // Currently running a recents animation, this will get called early because
-                        // we show the recents animation target activity immediately when the
-                        // animation starts. In this case, we should defer sending the finished
-                        // callback until the animation successfully finishes
-                        return;
-                    } else {
-                        atoken.mEnteringAnimation = false;
-                        try {
-                            mActivityTaskManager.notifyEnterAnimationComplete(atoken.token);
-                        } catch (RemoteException e) {
-                        }
+                // We should also defer sending the finished callback until the recents animation
+                // successfully finishes.
+                if (atoken.mEnteringAnimation && !isRecentsAnimationTarget) {
+                    atoken.mEnteringAnimation = false;
+                    try {
+                        mActivityTaskManager.notifyEnterAnimationComplete(atoken.token);
+                    } catch (RemoteException e) {
                     }
                 }
             }
@@ -1270,14 +1272,7 @@
 
         // Add ourself to the Watchdog monitors.
         Watchdog.getInstance().addMonitor(this);
-
-        openSurfaceTransaction();
-        try {
-            createWatermarkInTransaction();
-        } finally {
-            closeSurfaceTransaction("createWatermarkInTransaction");
-        }
-
+        createWatermark();
         showEmulatorDisplayOverlayIfNeeded();
     }
 
@@ -1586,7 +1581,6 @@
 
             win.attach();
             mWindowMap.put(client.asBinder(), win);
-
             win.initAppOpsState();
 
             final boolean suspended = mPmInternal.isPackageSuspended(win.getOwningPackage(),
@@ -3290,10 +3284,12 @@
             }
 
             // Don't enable the screen until all existing windows have been drawn.
-            if (!mForceDisplayEnabled
-                    // TODO(multidisplay): Expand to all displays?
-                    && getDefaultDisplayContentLocked().checkWaitingForWindows()) {
-                return;
+            if (!mForceDisplayEnabled) {
+                for (int i = mRoot.getChildCount() - 1; i >= 0; i--) {
+                    if (mRoot.getChildAt(i).shouldWaitForSystemDecorWindowsOnBoot()) {
+                        return;
+                    }
+                }
             }
 
             if (!mBootAnimationStopped) {
@@ -3434,60 +3430,45 @@
 
     public void showCircularMask(boolean visible) {
         synchronized (mGlobalLock) {
+            if (visible) {
+                // TODO(multi-display): support multiple displays
+                if (mCircularDisplayMask == null) {
+                    int screenOffset = mContext.getResources().getInteger(
+                            com.android.internal.R.integer.config_windowOutsetBottom);
+                    int maskThickness = mContext.getResources().getDimensionPixelSize(
+                            com.android.internal.R.dimen.circular_display_mask_thickness);
 
-            if (SHOW_LIGHT_TRANSACTIONS) Slog.i(TAG_WM,
-                    ">>> OPEN TRANSACTION showCircularMask(visible=" + visible + ")");
-            openSurfaceTransaction();
-            try {
-                if (visible) {
-                    // TODO(multi-display): support multiple displays
-                    if (mCircularDisplayMask == null) {
-                        int screenOffset = mContext.getResources().getInteger(
-                                com.android.internal.R.integer.config_windowOutsetBottom);
-                        int maskThickness = mContext.getResources().getDimensionPixelSize(
-                                com.android.internal.R.dimen.circular_display_mask_thickness);
 
-                        mCircularDisplayMask = new CircularDisplayMask(mSurfaceFactory,
-                                getDefaultDisplayContentLocked(),
-                                mPolicy.getWindowLayerFromTypeLw(
-                                        WindowManager.LayoutParams.TYPE_POINTER)
-                                        * TYPE_LAYER_MULTIPLIER + 10, screenOffset, maskThickness);
+                    if (SHOW_LIGHT_TRANSACTIONS) {
+                        Slog.i(TAG_WM,
+                                ">>> showCircularMask(visible=" + visible + ")");
                     }
-                    mCircularDisplayMask.setVisibility(true);
-                } else if (mCircularDisplayMask != null) {
-                    mCircularDisplayMask.setVisibility(false);
-                    mCircularDisplayMask = null;
+                    mCircularDisplayMask = new CircularDisplayMask(mSurfaceFactory,
+                            getDefaultDisplayContentLocked(), mPolicy.getWindowLayerFromTypeLw(
+                            WindowManager.LayoutParams.TYPE_POINTER) * TYPE_LAYER_MULTIPLIER
+                            + 10, screenOffset, maskThickness, mTransaction);
                 }
-            } finally {
-                closeSurfaceTransaction("showCircularMask");
-                if (SHOW_LIGHT_TRANSACTIONS) Slog.i(TAG_WM,
-                        "<<< CLOSE TRANSACTION showCircularMask(visible=" + visible + ")");
+                mCircularDisplayMask.setVisibility(true, mTransaction);
+            } else if (mCircularDisplayMask != null) {
+                mCircularDisplayMask.setVisibility(false, mTransaction);
+                mCircularDisplayMask = null;
             }
+            mTransaction.apply();
         }
     }
 
     public void showEmulatorDisplayOverlay() {
         synchronized (mGlobalLock) {
 
-            if (SHOW_LIGHT_TRANSACTIONS) Slog.i(TAG_WM,
-                    ">>> OPEN TRANSACTION showEmulatorDisplayOverlay");
-            openSurfaceTransaction();
-            try {
-                if (mEmulatorDisplayOverlay == null) {
-                    mEmulatorDisplayOverlay = new EmulatorDisplayOverlay(
-                            mSurfaceFactory,
-                            mContext,
-                            getDefaultDisplayContentLocked(),
-                            mPolicy.getWindowLayerFromTypeLw(
-                                    WindowManager.LayoutParams.TYPE_POINTER)
-                                    * TYPE_LAYER_MULTIPLIER + 10);
-                }
-                mEmulatorDisplayOverlay.setVisibility(true);
-            } finally {
-                closeSurfaceTransaction("showEmulatorDisplayOverlay");
-                if (SHOW_LIGHT_TRANSACTIONS) Slog.i(TAG_WM,
-                        "<<< CLOSE TRANSACTION showEmulatorDisplayOverlay");
+            if (SHOW_LIGHT_TRANSACTIONS) Slog.i(TAG_WM, ">>> showEmulatorDisplayOverlay");
+            if (mEmulatorDisplayOverlay == null) {
+                mEmulatorDisplayOverlay = new EmulatorDisplayOverlay(mSurfaceFactory, mContext,
+                        getDefaultDisplayContentLocked(),
+                        mPolicy.getWindowLayerFromTypeLw(WindowManager.LayoutParams.TYPE_POINTER)
+                                * TYPE_LAYER_MULTIPLIER + 10, mTransaction);
             }
+            mEmulatorDisplayOverlay.setVisibility(true, mTransaction);
+            mTransaction.apply();
         }
     }
 
@@ -3516,23 +3497,16 @@
                 return;
             }
 
-            if (SHOW_VERBOSE_TRANSACTIONS) Slog.i(TAG_WM,
-                    ">>> OPEN TRANSACTION showStrictModeViolation");
+            if (SHOW_VERBOSE_TRANSACTIONS) Slog.i(TAG_WM, ">>> showStrictModeViolation");
             // TODO: Modify this to use the surface trace once it is not going crazy.
             // b/31532461
-            SurfaceControl.openTransaction();
-            try {
-                // TODO(multi-display): support multiple displays
-                if (mStrictModeFlash == null) {
-                    mStrictModeFlash = new StrictModeFlash(mSurfaceFactory,
-                            getDefaultDisplayContentLocked());
-                }
-                mStrictModeFlash.setVisibility(on);
-            } finally {
-                SurfaceControl.closeTransaction();
-                if (SHOW_VERBOSE_TRANSACTIONS) Slog.i(TAG_WM,
-                        "<<< CLOSE TRANSACTION showStrictModeViolation");
+            // TODO(multi-display): support multiple displays
+            if (mStrictModeFlash == null) {
+                mStrictModeFlash = new StrictModeFlash(mSurfaceFactory,
+                        getDefaultDisplayContentLocked(), mTransaction);
             }
+            mStrictModeFlash.setVisibility(on, mTransaction);
+            mTransaction.apply();
         }
     }
 
@@ -4733,12 +4707,12 @@
 
                 case WAITING_FOR_DRAWN_TIMEOUT: {
                     Runnable callback = null;
+                    final WindowContainer container = (WindowContainer) msg.obj;
                     synchronized (mGlobalLock) {
                         ProtoLog.w(WM_ERROR, "Timeout waiting for drawn: undrawn=%s",
-                                mWaitingForDrawn);
-                        mWaitingForDrawn.clear();
-                        callback = mWaitingForDrawnCallback;
-                        mWaitingForDrawnCallback = null;
+                                container.mWaitingForDrawn);
+                        container.mWaitingForDrawn.clear();
+                        callback = mWaitingForDrawnCallbacks.remove(container);
                     }
                     if (callback != null) {
                         callback.run();
@@ -4770,9 +4744,9 @@
                 }
                 case ALL_WINDOWS_DRAWN: {
                     Runnable callback;
+                    final WindowContainer container = (WindowContainer) msg.obj;
                     synchronized (mGlobalLock) {
-                        callback = mWaitingForDrawnCallback;
-                        mWaitingForDrawnCallback = null;
+                        callback = mWaitingForDrawnCallbacks.remove(container);
                     }
                     if (callback != null) {
                         callback.run();
@@ -5262,30 +5236,32 @@
     }
 
     void checkDrawnWindowsLocked() {
-        if (mWaitingForDrawn.isEmpty() || mWaitingForDrawnCallback == null) {
+        if (mWaitingForDrawnCallbacks.isEmpty()) {
             return;
         }
-        for (int j = mWaitingForDrawn.size() - 1; j >= 0; j--) {
-            WindowState win = mWaitingForDrawn.get(j);
-            ProtoLog.i(WM_DEBUG_SCREEN_ON,
+        mWaitingForDrawnCallbacks.forEach((container, callback) -> {
+            for (int j = container.mWaitingForDrawn.size() - 1; j >= 0; j--) {
+                final WindowState win = (WindowState) container.mWaitingForDrawn.get(j);
+                ProtoLog.i(WM_DEBUG_SCREEN_ON,
                         "Waiting for drawn %s: removed=%b visible=%b mHasSurface=%b drawState=%d",
                         win, win.mRemoved, win.isVisibleLw(), win.mHasSurface,
                         win.mWinAnimator.mDrawState);
-            if (win.mRemoved || !win.mHasSurface || !win.isVisibleByPolicy()) {
-                // Window has been removed or hidden; no draw will now happen, so stop waiting.
-                ProtoLog.w(WM_DEBUG_SCREEN_ON, "Aborted waiting for drawn: %s", win);
-                mWaitingForDrawn.remove(win);
-            } else if (win.hasDrawnLw()) {
-                // Window is now drawn (and shown).
-                ProtoLog.d(WM_DEBUG_SCREEN_ON, "Window drawn win=%s", win);
-                mWaitingForDrawn.remove(win);
+                if (win.mRemoved || !win.mHasSurface || !win.isVisibleByPolicy()) {
+                    // Window has been removed or hidden; no draw will now happen, so stop waiting.
+                    ProtoLog.w(WM_DEBUG_SCREEN_ON, "Aborted waiting for drawn: %s", win);
+                    container.mWaitingForDrawn.remove(win);
+                } else if (win.hasDrawnLw()) {
+                    // Window is now drawn (and shown).
+                    ProtoLog.d(WM_DEBUG_SCREEN_ON, "Window drawn win=%s", win);
+                    container.mWaitingForDrawn.remove(win);
+                }
             }
-        }
-        if (mWaitingForDrawn.isEmpty()) {
-            ProtoLog.d(WM_DEBUG_SCREEN_ON, "All windows drawn!");
-            mH.removeMessages(H.WAITING_FOR_DRAWN_TIMEOUT);
-            mH.sendEmptyMessage(H.ALL_WINDOWS_DRAWN);
-        }
+            if (container.mWaitingForDrawn.isEmpty()) {
+                ProtoLog.d(WM_DEBUG_SCREEN_ON, "All windows drawn!");
+                mH.removeMessages(H.WAITING_FOR_DRAWN_TIMEOUT, container);
+                mH.sendMessage(mH.obtainMessage(H.ALL_WINDOWS_DRAWN, container));
+            }
+        });
     }
 
     void setHoldScreenLocked(final Session newHoldScreen) {
@@ -5517,7 +5493,7 @@
         return val;
     }
 
-    void createWatermarkInTransaction() {
+    void createWatermark() {
         if (mWatermark != null) {
             return;
         }
@@ -5535,8 +5511,8 @@
                     // TODO(multi-display): Show watermarks on secondary displays.
                     final DisplayContent displayContent = getDefaultDisplayContentLocked();
                     mWatermark = new Watermark(mSurfaceFactory, displayContent,
-                            displayContent.mRealDisplayMetrics,
-                            toks);
+                            displayContent.mRealDisplayMetrics, toks, mTransaction);
+                    mTransaction.apply();
                 }
             }
         } catch (FileNotFoundException e) {
@@ -5931,13 +5907,18 @@
                 }
             }
         }
-        if (mWaitingForDrawn.size() > 0) {
+        if (!mWaitingForDrawnCallbacks.isEmpty()) {
             pw.println();
             pw.println("  Clients waiting for these windows to be drawn:");
-            for (int i=mWaitingForDrawn.size()-1; i>=0; i--) {
-                WindowState win = mWaitingForDrawn.get(i);
-                pw.print("  Waiting #"); pw.print(i); pw.print(' '); pw.print(win);
-            }
+            mWaitingForDrawnCallbacks.forEach((wc, callback) -> {
+                pw.print("  WindowContainer ");
+                pw.println(wc.getName());
+                for (int i = wc.mWaitingForDrawn.size() - 1; i >= 0; i--) {
+                    final WindowState win = (WindowState) wc.mWaitingForDrawn.get(i);
+                    pw.print("  Waiting #"); pw.print(i); pw.print(' '); pw.print(win);
+                }
+            });
+
         }
         pw.println();
         pw.print("  mGlobalConfiguration="); pw.println(mRoot.getConfiguration());
@@ -7093,17 +7074,25 @@
         }
 
         @Override
-        public void waitForAllWindowsDrawn(Runnable callback, long timeout) {
+        public void waitForAllWindowsDrawn(Runnable callback, long timeout, int displayId) {
+            final WindowContainer container = displayId == INVALID_DISPLAY
+                    ? mRoot : mRoot.getDisplayContent(displayId);
+            if (container == null) {
+                // The waiting container doesn't exist, no need to wait to run the callback. Run and
+                // return;
+                callback.run();
+                return;
+            }
             boolean allWindowsDrawn = false;
             synchronized (mGlobalLock) {
-                mWaitingForDrawnCallback = callback;
-                getDefaultDisplayContentLocked().waitForAllWindowsDrawn();
+                container.waitForAllWindowsDrawn();
                 mWindowPlacerLocked.requestTraversal();
-                mH.removeMessages(H.WAITING_FOR_DRAWN_TIMEOUT);
-                if (mWaitingForDrawn.isEmpty()) {
+                mH.removeMessages(H.WAITING_FOR_DRAWN_TIMEOUT, container);
+                if (container.mWaitingForDrawn.isEmpty()) {
                     allWindowsDrawn = true;
                 } else {
-                    mH.sendEmptyMessageDelayed(H.WAITING_FOR_DRAWN_TIMEOUT, timeout);
+                    mWaitingForDrawnCallbacks.put(container, callback);
+                    mH.sendNewMessageDelayed(H.WAITING_FOR_DRAWN_TIMEOUT, container, timeout);
                     checkDrawnWindowsLocked();
                 }
             }
@@ -7300,6 +7289,29 @@
         }
 
         @Override
+        public void showImePostLayout(IBinder imeTargetWindowToken) {
+            synchronized (mGlobalLock) {
+                final WindowState imeTarget = mWindowMap.get(imeTargetWindowToken);
+                if (imeTarget == null) {
+                    return;
+                }
+                final DisplayContent displayContent = imeTarget.getDisplayContent();
+                if (displayContent == null) {
+                    Slog.w(TAG_WM, "Attempted to show IME on an IME target that does not exist: "
+                            + imeTarget.getName());
+                    return;
+                }
+                if (displayContent.isUntrustedVirtualDisplay()) {
+                    throw new SecurityException("Attempted to show IME on an untrusted "
+                            + "virtual display: " + displayContent.getDisplayId());
+                }
+
+                displayContent.getInsetsStateController().getImeSourceProvider()
+                        .scheduleShowImePostLayout(imeTarget);
+            }
+        }
+
+        @Override
         public boolean isUidAllowedOnDisplay(int displayId, int uid) {
             if (displayId == Display.DEFAULT_DISPLAY) {
                 return true;
@@ -7582,7 +7594,7 @@
     }
 
     private void onPointerDownOutsideFocusLocked(IBinder touchedToken) {
-        final WindowState touchedWindow = windowForClientLocked(null, touchedToken, false);
+        final WindowState touchedWindow = mInputToWindowMap.get(touchedToken);
         if (touchedWindow == null || !touchedWindow.canReceiveKeys()) {
             return;
         }
@@ -7633,7 +7645,7 @@
             // to do so because it seems possible to resume activities as part of a larger
             // transaction and it's too early to resume based on current order when performing
             // updateTopResumedActivityIfNeeded().
-            displayContent.mAcitvityDisplay.ensureActivitiesVisible(null /* starting */,
+            displayContent.mActivityDisplay.ensureActivitiesVisible(null /* starting */,
                     0 /* configChanges */, !PRESERVE_WINDOWS, true /* notifyClients */);
         }
     }
@@ -7655,9 +7667,9 @@
         clientChannel.transferTo(outInputChannel);
         clientChannel.dispose();
 
-        mInputManager.registerInputChannel(inputChannel, null /* generate new token */);
+        mInputManager.registerInputChannel(inputChannel);
 
-        InputWindowHandle h = new InputWindowHandle(null, null, displayId);
+        InputWindowHandle h = new InputWindowHandle(null, displayId);
         h.token = inputChannel.getToken();
         h.name = name;
         h.layoutParamsFlags = WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL;
@@ -7745,4 +7757,27 @@
             Binder.restoreCallingIdentity(token);
         }
     }
+
+    @Override
+    public boolean mirrorDisplay(int displayId, SurfaceControl outSurfaceControl) {
+        if (!checkCallingPermission(ACCESS_SURFACE_FLINGER, "mirrorDisplay()")) {
+            throw new SecurityException("Requires ACCESS_SURFACE_FLINGER permission");
+        }
+
+        final SurfaceControl displaySc;
+        synchronized (mGlobalLock) {
+            DisplayContent displayContent = mRoot.getDisplayContent(displayId);
+            if (displayContent == null) {
+                Slog.e(TAG, "Invalid displayId " + displayId + " for mirrorDisplay");
+                return false;
+            }
+
+            displaySc = displayContent.getSurfaceControl();
+        }
+
+        final SurfaceControl mirror = SurfaceControl.mirrorSurface(displaySc);
+        outSurfaceControl.copyFrom(mirror);
+
+        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 d7116d8..1c0d156 100644
--- a/services/core/java/com/android/server/wm/WindowProcessController.java
+++ b/services/core/java/com/android/server/wm/WindowProcessController.java
@@ -702,7 +702,7 @@
         }
         ActivityRecord hist = mActivities.get(0);
         intent.putExtra(HeavyWeightSwitcherActivity.KEY_CUR_APP, hist.packageName);
-        intent.putExtra(HeavyWeightSwitcherActivity.KEY_CUR_TASK, hist.getTaskRecord().taskId);
+        intent.putExtra(HeavyWeightSwitcherActivity.KEY_CUR_TASK, hist.getTaskRecord().mTaskId);
     }
 
     boolean shouldKillProcessForRemovedTask(TaskRecord tr) {
@@ -713,7 +713,7 @@
                 return false;
             }
             final TaskRecord otherTask = activity.getTaskRecord();
-            if (tr.taskId != otherTask.taskId && otherTask.inRecents) {
+            if (tr.mTaskId != otherTask.mTaskId && otherTask.inRecents) {
                 // Don't kill process(es) that has an activity in a different task that is
                 // also in recents.
                 return false;
diff --git a/services/core/java/com/android/server/wm/WindowState.java b/services/core/java/com/android/server/wm/WindowState.java
index d459f14..40bb059 100644
--- a/services/core/java/com/android/server/wm/WindowState.java
+++ b/services/core/java/com/android/server/wm/WindowState.java
@@ -197,6 +197,7 @@
 import android.view.View;
 import android.view.ViewTreeObserver;
 import android.view.WindowInfo;
+import android.view.WindowInsets.Type.InsetType;
 import android.view.WindowManager;
 import android.view.animation.Animation;
 import android.view.animation.AnimationUtils;
@@ -819,8 +820,7 @@
         mLastRequestedHeight = 0;
         mLayer = 0;
         mInputWindowHandle = new InputWindowHandle(
-                mAppToken != null ? mAppToken.mInputApplicationHandle : null, c,
-                    getDisplayId());
+                mAppToken != null ? mAppToken.mInputApplicationHandle : null, getDisplayId());
     }
 
     void attach() {
@@ -835,7 +835,7 @@
      */
     boolean inSizeCompatMode() {
         return (mAttrs.privateFlags & PRIVATE_FLAG_COMPATIBLE_WINDOW) != 0
-                || (mAppToken != null && mAppToken.inSizeCompatMode()
+                || (mAppToken != null && mAppToken.hasSizeCompatBounds()
                         // Exclude starting window because it is not displayed by the application.
                         && mAttrs.type != TYPE_APPLICATION_STARTING);
     }
@@ -2190,7 +2190,9 @@
         InputChannel[] inputChannels = InputChannel.openInputChannelPair(name);
         mInputChannel = inputChannels[0];
         mClientChannel = inputChannels[1];
-        mInputWindowHandle.token = mClient.asBinder();
+        mWmService.mInputManager.registerInputChannel(mInputChannel);
+        mClientChannel.setToken(mInputChannel.getToken());
+        mInputWindowHandle.token = mInputChannel.getToken();
         if (outInputChannel != null) {
             mClientChannel.transferTo(outInputChannel);
             mClientChannel.dispose();
@@ -2201,7 +2203,7 @@
             // Create dummy event receiver that simply reports all events as handled.
             mDeadWindowEventReceiver = new DeadWindowEventReceiver(mClientChannel);
         }
-        mWmService.mInputManager.registerInputChannel(mInputChannel, mClient.asBinder());
+        mWmService.mInputToWindowMap.put(mInputWindowHandle.token, this);
     }
 
     void disposeInputChannel() {
@@ -2222,6 +2224,7 @@
             mClientChannel = null;
         }
         mWmService.mKeyInterceptionInfoForToken.remove(mInputWindowHandle.token);
+        mWmService.mInputToWindowMap.remove(mInputWindowHandle.token);
         mInputWindowHandle.token = null;
     }
 
@@ -2319,7 +2322,7 @@
             }
             // The offset of compatibility bounds is applied to surface of {@link #AppWindowToken}
             // and frame, so it is unnecessary to translate twice in surface based coordinates.
-            final int surfaceOffsetX = mAppToken.inSizeCompatMode()
+            final int surfaceOffsetX = mAppToken.hasSizeCompatBounds()
                     ? mAppToken.getBounds().left : 0;
             mTmpRect.offset(surfaceOffsetX - mWindowFrames.mFrame.left, -mWindowFrames.mFrame.top);
             region.set(mTmpRect);
@@ -2423,15 +2426,15 @@
     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.mActivityRecord.canTurnScreenOn());
+                || (mAppToken != null && mAppToken.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.
         // 2. The WMS allows theater mode.
         // 3. No AWT or the AWT allows the screen to be turned on. This should only be true once
         // per resume to prevent the screen getting getting turned on for each relayout. Set
-        // canTurnScreenOn will be set to false so the window doesn't turn the screen on again
-        // during this resume.
+        // currentLaunchCanTurnScreenOn will be set to false so the window doesn't turn the screen
+        // on again during this resume.
         // 4. When the screen is not interactive. This is because when the screen is already
         // interactive, the value may persist until the next animation, which could potentially
         // be occurring while turning off the screen. This would lead to the screen incorrectly
@@ -2616,7 +2619,7 @@
     @Override
     public boolean canShowWhenLocked() {
         final boolean showBecauseOfActivity =
-                mAppToken != null && mAppToken.mActivityRecord.canShowWhenLocked();
+                mAppToken != null && mAppToken.canShowWhenLocked();
         final boolean showBecauseOfWindow = (getAttrs().flags & FLAG_SHOW_WHEN_LOCKED) != 0;
         return showBecauseOfActivity || showBecauseOfWindow;
     }
@@ -3365,6 +3368,15 @@
         }
     }
 
+    @Override
+    public void showInsets(@InsetType int types, boolean fromIme) {
+        try {
+            mClient.showInsets(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
@@ -3487,7 +3499,7 @@
     @Override
     void setWaitingForDrawnIfResizingChanged() {
         if (isDragResizeChanged()) {
-            mWmService.mWaitingForDrawn.add(this);
+            mWmService.mRoot.mWaitingForDrawn.add(this);
         }
         super.setWaitingForDrawnIfResizingChanged();
     }
diff --git a/services/core/java/com/android/server/wm/WindowStateAnimator.java b/services/core/java/com/android/server/wm/WindowStateAnimator.java
index 3dcf6ec..1328273 100644
--- a/services/core/java/com/android/server/wm/WindowStateAnimator.java
+++ b/services/core/java/com/android/server/wm/WindowStateAnimator.java
@@ -506,9 +506,8 @@
                 flags |= SurfaceControl.OPAQUE;
             }
 
-            mSurfaceController = new WindowSurfaceController(mSession.mSurfaceSession,
-                    attrs.getTitle().toString(), width, height, format, flags, this,
-                    windowType, ownerUid);
+            mSurfaceController = new WindowSurfaceController(attrs.getTitle().toString(), width,
+                    height, format, flags, this, windowType, ownerUid);
             mSurfaceController.setColorSpaceAgnostic((attrs.privateFlags
                     & WindowManager.LayoutParams.PRIVATE_FLAG_COLOR_SPACE_AGNOSTIC) != 0);
 
diff --git a/services/core/java/com/android/server/wm/WindowSurfaceController.java b/services/core/java/com/android/server/wm/WindowSurfaceController.java
index 49f27a1..0b4ea99 100644
--- a/services/core/java/com/android/server/wm/WindowSurfaceController.java
+++ b/services/core/java/com/android/server/wm/WindowSurfaceController.java
@@ -37,8 +37,8 @@
 import android.util.Slog;
 import android.util.proto.ProtoOutputStream;
 import android.view.SurfaceControl;
-import android.view.SurfaceSession;
 import android.view.WindowContentFrameStats;
+import android.view.WindowManager;
 
 import com.android.server.protolog.common.ProtoLog;
 
@@ -85,7 +85,7 @@
 
     private final SurfaceControl.Transaction mTmpTransaction;
 
-    public WindowSurfaceController(SurfaceSession s, String name, int w, int h, int format,
+    WindowSurfaceController(String name, int w, int h, int format,
             int flags, WindowStateAnimator animator, int windowType, int ownerUid) {
         mAnimator = animator;
 
@@ -109,6 +109,13 @@
                 .setFlags(flags)
                 .setMetadata(METADATA_WINDOW_TYPE, windowType)
                 .setMetadata(METADATA_OWNER_UID, ownerUid);
+
+        if ((win.getAttrs().privateFlags &
+                WindowManager.LayoutParams.PRIVATE_FLAG_USE_BLAST) != 0) {
+            b.setContainerLayer();
+        }
+
+
         mSurfaceControl = b.build();
         Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER);
     }
diff --git a/services/core/java/com/android/server/wm/WindowToken.java b/services/core/java/com/android/server/wm/WindowToken.java
index fbfb028..5b362c3 100644
--- a/services/core/java/com/android/server/wm/WindowToken.java
+++ b/services/core/java/com/android/server/wm/WindowToken.java
@@ -120,7 +120,9 @@
         mPersistOnEmpty = persistOnEmpty;
         mOwnerCanManageAppTokens = ownerCanManageAppTokens;
         mRoundedCornerOverlay = roundedCornerOverlay;
-        onDisplayChanged(dc);
+        if (dc != null) {
+            onDisplayChanged(dc);
+        }
     }
 
     void setHidden(boolean hidden) {
diff --git a/services/core/jni/Android.bp b/services/core/jni/Android.bp
index d9c7fed..bcd1713 100644
--- a/services/core/jni/Android.bp
+++ b/services/core/jni/Android.bp
@@ -141,6 +141,7 @@
         "android.hardware.vibrator@1.1",
         "android.hardware.vibrator@1.2",
         "android.hardware.vibrator@1.3",
+        "android.hardware.vibrator@1.4",
         "android.hardware.vr@1.0",
         "android.frameworks.schedulerservice@1.0",
         "android.frameworks.sensorservice@1.0",
diff --git a/services/core/jni/com_android_server_VibratorService.cpp b/services/core/jni/com_android_server_VibratorService.cpp
index 7aa9c7c..a8c7682 100644
--- a/services/core/jni/com_android_server_VibratorService.cpp
+++ b/services/core/jni/com_android_server_VibratorService.cpp
@@ -16,17 +16,12 @@
 
 #define LOG_TAG "VibratorService"
 
-#include <android/hardware/vibrator/1.0/IVibrator.h>
-#include <android/hardware/vibrator/1.0/types.h>
-#include <android/hardware/vibrator/1.0/IVibrator.h>
-#include <android/hardware/vibrator/1.1/types.h>
-#include <android/hardware/vibrator/1.2/IVibrator.h>
-#include <android/hardware/vibrator/1.2/types.h>
-#include <android/hardware/vibrator/1.3/IVibrator.h>
+#include <android/hardware/vibrator/1.4/IVibrator.h>
 
 #include "jni.h"
 #include <nativehelper/JNIHelp.h>
 #include "android_runtime/AndroidRuntime.h"
+#include "core_jni_helpers.h"
 
 #include <utils/misc.h>
 #include <utils/Log.h>
@@ -36,6 +31,7 @@
 #include <stdio.h>
 
 using android::hardware::Return;
+using android::hardware::Void;
 using android::hardware::vibrator::V1_0::EffectStrength;
 using android::hardware::vibrator::V1_0::Status;
 using android::hardware::vibrator::V1_1::Effect_1_1;
@@ -44,9 +40,32 @@
 namespace V1_1 = android::hardware::vibrator::V1_1;
 namespace V1_2 = android::hardware::vibrator::V1_2;
 namespace V1_3 = android::hardware::vibrator::V1_3;
+namespace V1_4 = android::hardware::vibrator::V1_4;
 
 namespace android {
 
+static jmethodID sMethodIdOnComplete;
+
+class VibratorCallback : public V1_4::IVibratorCallback {
+    public:
+        VibratorCallback(JNIEnv *env, jobject vibration) :
+        mVibration(MakeGlobalRefOrDie(env, vibration)) {}
+
+        ~VibratorCallback() {
+            JNIEnv *env = AndroidRuntime::getJNIEnv();
+            env->DeleteGlobalRef(mVibration);
+        }
+
+        Return<void> onComplete() override {
+            auto env = AndroidRuntime::getJNIEnv();
+            env->CallVoidMethod(mVibration, sMethodIdOnComplete);
+            return Void();
+        }
+
+    private:
+        jobject mVibration;
+};
+
 static constexpr int NUM_TRIES = 2;
 
 // Creates a Return<R> with STATUS::EX_NULL_POINTER.
@@ -119,17 +138,17 @@
     return val >= *iter.begin() && val <= *std::prev(iter.end());
 }
 
-static void vibratorInit(JNIEnv /* env */, jobject /* clazz */)
+static void vibratorInit(JNIEnv *env, jclass clazz)
 {
     halCall(&V1_0::IVibrator::ping).isOk();
 }
 
-static jboolean vibratorExists(JNIEnv* /* env */, jobject /* clazz */)
+static jboolean vibratorExists(JNIEnv* /* env */, jclass /* clazz */)
 {
     return halCall(&V1_0::IVibrator::ping).isOk() ? JNI_TRUE : JNI_FALSE;
 }
 
-static void vibratorOn(JNIEnv* /* env */, jobject /* clazz */, jlong timeout_ms)
+static void vibratorOn(JNIEnv* /* env */, jclass /* clazz */, jlong timeout_ms)
 {
     Status retStatus = halCall(&V1_0::IVibrator::on, timeout_ms).withDefault(Status::UNKNOWN_ERROR);
     if (retStatus != Status::OK) {
@@ -137,7 +156,7 @@
     }
 }
 
-static void vibratorOff(JNIEnv* /* env */, jobject /* clazz */)
+static void vibratorOff(JNIEnv* /* env */, jclass /* clazz */)
 {
     Status retStatus = halCall(&V1_0::IVibrator::off).withDefault(Status::UNKNOWN_ERROR);
     if (retStatus != Status::OK) {
@@ -145,11 +164,11 @@
     }
 }
 
-static jlong vibratorSupportsAmplitudeControl(JNIEnv*, jobject) {
+static jlong vibratorSupportsAmplitudeControl(JNIEnv*, jclass) {
     return halCall(&V1_0::IVibrator::supportsAmplitudeControl).withDefault(false);
 }
 
-static void vibratorSetAmplitude(JNIEnv*, jobject, jint amplitude) {
+static void vibratorSetAmplitude(JNIEnv*, jclass, jint amplitude) {
     Status status = halCall(&V1_0::IVibrator::setAmplitude, static_cast<uint32_t>(amplitude))
         .withDefault(Status::UNKNOWN_ERROR);
     if (status != Status::OK) {
@@ -158,11 +177,11 @@
     }
 }
 
-static jboolean vibratorSupportsExternalControl(JNIEnv*, jobject) {
+static jboolean vibratorSupportsExternalControl(JNIEnv*, jclass) {
     return halCall(&V1_3::IVibrator::supportsExternalControl).withDefault(false);
 }
 
-static void vibratorSetExternalControl(JNIEnv*, jobject, jboolean enabled) {
+static void vibratorSetExternalControl(JNIEnv*, jclass, jboolean enabled) {
     Status status = halCall(&V1_3::IVibrator::setExternalControl, static_cast<uint32_t>(enabled))
         .withDefault(Status::UNKNOWN_ERROR);
     if (status != Status::OK) {
@@ -171,7 +190,8 @@
     }
 }
 
-static jlong vibratorPerformEffect(JNIEnv*, jobject, jlong effect, jint strength) {
+static jlong vibratorPerformEffect(JNIEnv* env, jclass, jlong effect, jint strength,
+                                   jobject vibration) {
     Status status;
     uint32_t lengthMs;
     auto callback = [&status, &lengthMs](Status retStatus, uint32_t retLengthMs) {
@@ -181,7 +201,11 @@
     EffectStrength effectStrength(static_cast<EffectStrength>(strength));
 
     Return<void> ret;
-    if (isValidEffect<V1_0::Effect>(effect)) {
+    if (auto hal = getHal<V1_4::IVibrator>(); hal && isValidEffect<V1_3::Effect>(effect)) {
+        sp<VibratorCallback> effectCallback = new VibratorCallback(env, vibration);
+        ret = hal->call(&V1_4::IVibrator::perform_1_4, static_cast<V1_3::Effect>(effect),
+                effectStrength, effectCallback, callback);
+    } else if (isValidEffect<V1_0::Effect>(effect)) {
         ret = halCall(&V1_0::IVibrator::perform, static_cast<V1_0::Effect>(effect),
                 effectStrength, callback);
     } else if (isValidEffect<Effect_1_1>(effect)) {
@@ -218,6 +242,10 @@
     return -1;
 }
 
+static jlong vibratorGetCapabilities(JNIEnv*, jclass) {
+    return halCall(&V1_4::IVibrator::getCapabilities).withDefault(0);
+}
+
 static const JNINativeMethod method_table[] = {
     { "vibratorExists", "()Z", (void*)vibratorExists },
     { "vibratorInit", "()V", (void*)vibratorInit },
@@ -225,13 +253,18 @@
     { "vibratorOff", "()V", (void*)vibratorOff },
     { "vibratorSupportsAmplitudeControl", "()Z", (void*)vibratorSupportsAmplitudeControl},
     { "vibratorSetAmplitude", "(I)V", (void*)vibratorSetAmplitude},
-    { "vibratorPerformEffect", "(JJ)J", (void*)vibratorPerformEffect},
+    { "vibratorPerformEffect", "(JJLcom/android/server/VibratorService$Vibration;)J",
+        (void*)vibratorPerformEffect},
     { "vibratorSupportsExternalControl", "()Z", (void*)vibratorSupportsExternalControl},
     { "vibratorSetExternalControl", "(Z)V", (void*)vibratorSetExternalControl},
+    { "vibratorGetCapabilities", "()J", (void*)vibratorGetCapabilities},
 };
 
 int register_android_server_VibratorService(JNIEnv *env)
 {
+    sMethodIdOnComplete = GetMethodIDOrDie(env,
+            FindClassOrDie(env, "com/android/server/VibratorService$Vibration"),
+            "onComplete", "()V");
     return jniRegisterNativeMethods(env, "com/android/server/VibratorService",
             method_table, NELEM(method_table));
 }
diff --git a/services/devicepolicy/TEST_MAPPING b/services/devicepolicy/TEST_MAPPING
index a5ee3e2..3d86cf3 100644
--- a/services/devicepolicy/TEST_MAPPING
+++ b/services/devicepolicy/TEST_MAPPING
@@ -1,5 +1,5 @@
 {
-  "presubmit": [
+  "presubmit-devicepolicy": [
     {
       "name": "CtsDevicePolicyManagerTestCases",
       "options": [
@@ -12,7 +12,7 @@
       ]
     }
   ],
-  "postsubmit": [
+  "postsubmit-devicepolicy": [
     {
       "name": "CtsDevicePolicyManagerTestCases"
     }
diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
index c3ff285..9569ac8 100644
--- a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
+++ b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
@@ -2186,7 +2186,7 @@
         }
 
         void postOnSystemServerInitThreadPool(Runnable runnable) {
-            SystemServerInitThreadPool.get().submit(runnable, LOG_TAG);
+            SystemServerInitThreadPool.submit(runnable, LOG_TAG);
         }
 
         public TransferOwnershipMetadataManager newTransferOwnershipMetadataManager() {
@@ -11320,6 +11320,28 @@
             }
         }
 
+        @Override
+        public boolean isActiveSupervisionApp(int uid) {
+            synchronized (getLockObject()) {
+                final ActiveAdmin admin = getActiveAdminWithPolicyForUidLocked(
+                        null, DeviceAdminInfo.USES_POLICY_PROFILE_OWNER, uid);
+                if (admin == null) {
+                    return false;
+                }
+
+                final String supervisionString = mContext.getResources().getString(
+                        com.android.internal.R.string
+                                .config_defaultSupervisionProfileOwnerComponent);
+                if (supervisionString == null) {
+                    return false;
+                }
+
+                final ComponentName supervisorComponent = ComponentName.unflattenFromString(
+                        supervisionString);
+                return admin.info.getComponent().equals(supervisorComponent);
+            }
+        }
+
         private void notifyCrossProfileProvidersChanged(int userId, List<String> packages) {
             final List<OnCrossProfileWidgetProvidersChangeListener> listeners;
             synchronized (getLockObject()) {
@@ -11902,10 +11924,13 @@
                     try {
                         int uid = packageManager.getPackageUidAsUser(packageName,
                                 user.getIdentifier());
-
-                        // TODO: Prevent noting the app-op
-                        granted = PermissionChecker.checkPermission(mContext, permission, -1,
-                                uid, packageName);
+                        if (PermissionChecker.checkPermissionForPreflight(mContext, permission,
+                                PermissionChecker.PID_UNKNOWN, uid, packageName)
+                                        != PermissionChecker.PERMISSION_GRANTED) {
+                            granted = PackageManager.PERMISSION_DENIED;
+                        } else {
+                            granted = PackageManager.PERMISSION_GRANTED;
+                        }
                     } catch (NameNotFoundException e) {
                         throw new RemoteException(
                                 "Cannot check if " + permission + "is a runtime permission", e,
diff --git a/services/java/com/android/server/SystemServer.java b/services/java/com/android/server/SystemServer.java
index de65002..4cf98d3 100644
--- a/services/java/com/android/server/SystemServer.java
+++ b/services/java/com/android/server/SystemServer.java
@@ -501,7 +501,7 @@
                     mRuntimeStartElapsedTime, mRuntimeStartUptime);
             LocalServices.addService(SystemServiceManager.class, mSystemServiceManager);
             // Prepare the thread pool for init tasks that can be parallelized
-            SystemServerInitThreadPool.get();
+            SystemServerInitThreadPool.start();
         } finally {
             t.traceEnd();  // InitBeforeStartServices
         }
@@ -635,7 +635,7 @@
         Slog.i(TAG, "Reading configuration...");
         final String TAG_SYSTEM_CONFIG = "ReadingSystemConfig";
         t.traceBegin(TAG_SYSTEM_CONFIG);
-        SystemServerInitThreadPool.get().submit(SystemConfig::getInstance, TAG_SYSTEM_CONFIG);
+        SystemServerInitThreadPool.submit(SystemConfig::getInstance, TAG_SYSTEM_CONFIG);
         t.traceEnd();
 
         // Platform compat service is used by ActivityManagerService, PackageManagerService, and
@@ -821,7 +821,7 @@
         // service, and permissions service, therefore we start it after them.
         // Start sensor service in a separate thread. Completion should be checked
         // before using it.
-        mSensorServiceStart = SystemServerInitThreadPool.get().submit(() -> {
+        mSensorServiceStart = SystemServerInitThreadPool.submit(() -> {
             TimingsTraceAndSlog traceLog = TimingsTraceAndSlog.newAsyncLog();
             traceLog.traceBegin(START_SENSOR_SERVICE);
             startSensorService();
@@ -946,7 +946,7 @@
             // ensure that it completes before the 32 bit relro process is forked
             // from the zygote. In the event that it takes too long, the webview
             // RELRO process will block, but it will do so without holding any locks.
-            mZygotePreload = SystemServerInitThreadPool.get().submit(() -> {
+            mZygotePreload = SystemServerInitThreadPool.submit(() -> {
                 try {
                     Slog.i(TAG, SECONDARY_ZYGOTE_PRELOAD);
                     TimingsTraceAndSlog traceLog = TimingsTraceAndSlog.newAsyncLog();
@@ -1058,7 +1058,7 @@
             // Start receiving calls from HIDL services. Start in in a separate thread
             // because it need to connect to SensorManager. This have to start
             // after START_SENSOR_SERVICE is done.
-            SystemServerInitThreadPool.get().submit(() -> {
+            SystemServerInitThreadPool.submit(() -> {
                 TimingsTraceAndSlog traceLog = TimingsTraceAndSlog.newAsyncLog();
                 traceLog.traceBegin(START_HIDL_SERVICES);
                 startHidlServices();
@@ -2050,7 +2050,7 @@
             final String WEBVIEW_PREPARATION = "WebViewFactoryPreparation";
             Future<?> webviewPrep = null;
             if (!mOnlyCore && mWebViewUpdateService != null) {
-                webviewPrep = SystemServerInitThreadPool.get().submit(() -> {
+                webviewPrep = SystemServerInitThreadPool.submit(() -> {
                     Slog.i(TAG, WEBVIEW_PREPARATION);
                     TimingsTraceAndSlog traceLog = TimingsTraceAndSlog.newAsyncLog();
                     traceLog.traceBegin(WEBVIEW_PREPARATION);
diff --git a/services/tests/mockingservicestests/src/com/android/server/DeviceIdleControllerTest.java b/services/tests/mockingservicestests/src/com/android/server/DeviceIdleControllerTest.java
index 108b017..9c97305 100644
--- a/services/tests/mockingservicestests/src/com/android/server/DeviceIdleControllerTest.java
+++ b/services/tests/mockingservicestests/src/com/android/server/DeviceIdleControllerTest.java
@@ -17,6 +17,7 @@
 
 import static androidx.test.InstrumentationRegistry.getContext;
 
+import static com.android.dx.mockito.inline.extended.ExtendedMockito.doAnswer;
 import static com.android.dx.mockito.inline.extended.ExtendedMockito.doNothing;
 import static com.android.dx.mockito.inline.extended.ExtendedMockito.doReturn;
 import static com.android.dx.mockito.inline.extended.ExtendedMockito.inOrder;
@@ -31,6 +32,7 @@
 import static com.android.server.DeviceIdleController.LIGHT_STATE_OVERRIDE;
 import static com.android.server.DeviceIdleController.LIGHT_STATE_PRE_IDLE;
 import static com.android.server.DeviceIdleController.LIGHT_STATE_WAITING_FOR_NETWORK;
+import static com.android.server.DeviceIdleController.MSG_REPORT_STATIONARY_STATUS;
 import static com.android.server.DeviceIdleController.STATE_ACTIVE;
 import static com.android.server.DeviceIdleController.STATE_IDLE;
 import static com.android.server.DeviceIdleController.STATE_IDLE_MAINTENANCE;
@@ -51,6 +53,7 @@
 import static org.mockito.ArgumentMatchers.anyInt;
 import static org.mockito.ArgumentMatchers.anyLong;
 import static org.mockito.ArgumentMatchers.anyString;
+import static org.mockito.ArgumentMatchers.argThat;
 import static org.mockito.ArgumentMatchers.eq;
 import static org.mockito.ArgumentMatchers.longThat;
 import static org.mockito.Mockito.atLeastOnce;
@@ -72,6 +75,7 @@
 import android.net.NetworkInfo;
 import android.os.Handler;
 import android.os.Looper;
+import android.os.Message;
 import android.os.PowerManager;
 import android.os.PowerManagerInternal;
 import android.os.PowerSaveState;
@@ -87,11 +91,13 @@
 import org.junit.Before;
 import org.junit.Test;
 import org.junit.runner.RunWith;
-import org.mockito.Answers;
+import org.mockito.ArgumentCaptor;
 import org.mockito.InOrder;
 import org.mockito.Mock;
 import org.mockito.MockitoSession;
+import org.mockito.invocation.InvocationOnMock;
 import org.mockito.quality.Strictness;
+import org.mockito.stubbing.Answer;
 
 /**
  * Tests for {@link com.android.server.DeviceIdleController}.
@@ -99,6 +105,7 @@
 @RunWith(AndroidJUnit4.class)
 public class DeviceIdleControllerTest {
     private DeviceIdleController mDeviceIdleController;
+    private DeviceIdleController.MyHandler mHandler;
     private AnyMotionDetectorForTest mAnyMotionDetector;
     private AppStateTrackerForTest mAppStateTracker;
     private DeviceIdleController.Constants mConstants;
@@ -108,12 +115,10 @@
     @Mock
     private AlarmManager mAlarmManager;
     @Mock
-    private ConnectivityService mConnectivityService;
+    private ConnectivityManager mConnectivityManager;
     @Mock
     private ContentResolver mContentResolver;
     @Mock
-    private DeviceIdleController.MyHandler mHandler;
-    @Mock
     private IActivityManager mIActivityManager;
     @Mock
     private LocationManager mLocationManager;
@@ -127,7 +132,7 @@
     private SensorManager mSensorManager;
 
     class InjectorForTest extends DeviceIdleController.Injector {
-        ConnectivityService connectivityService;
+        ConnectivityManager connectivityManager;
         LocationManager locationManager;
         ConstraintController constraintController;
         // Freeze time for testing.
@@ -155,8 +160,8 @@
         }
 
         @Override
-        ConnectivityService getConnectivityService() {
-            return connectivityService;
+        ConnectivityManager getConnectivityManager() {
+            return connectivityManager;
         }
 
         @Override
@@ -171,6 +176,23 @@
 
         @Override
         DeviceIdleController.MyHandler getHandler(DeviceIdleController controller) {
+            if (mHandler == null) {
+                mHandler = controller.new MyHandler(getContext().getMainLooper());
+                spyOn(mHandler);
+                doNothing().when(mHandler).handleMessage(argThat((message) ->
+                        message.what != MSG_REPORT_STATIONARY_STATUS));
+                doAnswer(new Answer<Boolean>() {
+                    @Override
+                    public Boolean answer(InvocationOnMock invocation) throws Throwable {
+                        Message msg = invocation.getArgument(0);
+                        mHandler.handleMessage(msg);
+                        return true;
+                    }
+                }).when(mHandler).sendMessageDelayed(
+                        argThat((message) -> message.what == MSG_REPORT_STATIONARY_STATUS),
+                        anyLong());
+            }
+
             return mHandler;
         }
 
@@ -236,6 +258,19 @@
         }
     }
 
+    private class StationaryListenerForTest implements DeviceIdleInternal.StationaryListener {
+        boolean motionExpected = false;
+        boolean isStationary = false;
+
+        @Override
+        public void onDeviceStationaryChanged(boolean isStationary) {
+            if (isStationary == motionExpected) {
+                fail("Unexpected device stationary status: " + isStationary);
+            }
+            this.isStationary = isStationary;
+        }
+    }
+
     @Before
     public void setUp() {
         mMockingSession = mockitoSession()
@@ -265,8 +300,6 @@
         doReturn(true).when(mSensorManager).registerListener(any(), any(), anyInt());
         mAppStateTracker = new AppStateTrackerForTest(getContext(), Looper.getMainLooper());
         mAnyMotionDetector = new AnyMotionDetectorForTest();
-        mHandler = mock(DeviceIdleController.MyHandler.class, Answers.RETURNS_DEEP_STUBS);
-        doNothing().when(mHandler).handleMessage(any());
         mInjector = new InjectorForTest(getContext());
         doNothing().when(mContentResolver).registerContentObserver(any(), anyBoolean(), any());
 
@@ -347,19 +380,19 @@
     public void testUpdateConnectivityState() {
         // No connectivity service
         final boolean isConnected = mDeviceIdleController.isNetworkConnected();
-        mInjector.connectivityService = null;
+        mInjector.connectivityManager = null;
         mDeviceIdleController.updateConnectivityState(null);
         assertEquals(isConnected, mDeviceIdleController.isNetworkConnected());
 
         // No active network info
-        mInjector.connectivityService = mConnectivityService;
-        doReturn(null).when(mConnectivityService).getActiveNetworkInfo();
+        mInjector.connectivityManager = mConnectivityManager;
+        doReturn(null).when(mConnectivityManager).getActiveNetworkInfo();
         mDeviceIdleController.updateConnectivityState(null);
         assertFalse(mDeviceIdleController.isNetworkConnected());
 
         // Active network info says connected.
         final NetworkInfo ani = mock(NetworkInfo.class);
-        doReturn(ani).when(mConnectivityService).getActiveNetworkInfo();
+        doReturn(ani).when(mConnectivityManager).getActiveNetworkInfo();
         doReturn(true).when(ani).isConnected();
         mDeviceIdleController.updateConnectivityState(null);
         assertTrue(mDeviceIdleController.isNetworkConnected());
@@ -1724,6 +1757,86 @@
                 1.0f, curfactor, delta);
     }
 
+    @Test
+    public void testStationaryDetection_QuickDozeOff() {
+        setQuickDozeEnabled(false);
+        enterDeepState(STATE_IDLE);
+        // Regular progression through states, so time should have increased appropriately.
+        mInjector.nowElapsed += mConstants.IDLE_AFTER_INACTIVE_TIMEOUT + mConstants.SENSING_TIMEOUT
+                + mConstants.LOCATING_TIMEOUT;
+
+        StationaryListenerForTest stationaryListener = new StationaryListenerForTest();
+
+        mDeviceIdleController.registerStationaryListener(stationaryListener);
+
+        // Go to IDLE_MAINTENANCE
+        mDeviceIdleController.stepIdleStateLocked("testing");
+
+        // Back to IDLE
+        mDeviceIdleController.stepIdleStateLocked("testing");
+        assertTrue(stationaryListener.isStationary);
+
+        // Test motion
+        stationaryListener.motionExpected = true;
+        mDeviceIdleController.mMotionListener.onTrigger(null);
+        assertFalse(stationaryListener.isStationary);
+    }
+
+    @Test
+    public void testStationaryDetection_QuickDozeOn() {
+        setAlarmSoon(false);
+        enterDeepState(STATE_QUICK_DOZE_DELAY);
+        mDeviceIdleController.stepIdleStateLocked("testing");
+        verifyStateConditions(STATE_IDLE);
+        // Quick doze progression through states, so time should have increased appropriately.
+        mInjector.nowElapsed += mConstants.QUICK_DOZE_DELAY_TIMEOUT;
+        final ArgumentCaptor<AlarmManager.OnAlarmListener> alarmListener = ArgumentCaptor
+                .forClass(AlarmManager.OnAlarmListener.class);
+        doNothing().when(mAlarmManager).set(anyInt(), anyLong(), eq("DeviceIdleController.motion"),
+                alarmListener.capture(), any());
+
+        StationaryListenerForTest stationaryListener = new StationaryListenerForTest();
+
+        stationaryListener.motionExpected = true;
+        mDeviceIdleController.registerStationaryListener(stationaryListener);
+        assertFalse(stationaryListener.isStationary);
+
+        // Go to IDLE_MAINTENANCE
+        mDeviceIdleController.stepIdleStateLocked("testing");
+
+        mInjector.nowElapsed += mConstants.MOTION_INACTIVE_TIMEOUT / 2;
+
+        // Back to IDLE
+        mDeviceIdleController.stepIdleStateLocked("testing");
+
+        // Now enough time has passed.
+        mInjector.nowElapsed += mConstants.MOTION_INACTIVE_TIMEOUT / 2;
+        stationaryListener.motionExpected = false;
+        alarmListener.getValue().onAlarm();
+        assertTrue(stationaryListener.isStationary);
+
+        stationaryListener.motionExpected = true;
+        mDeviceIdleController.mMotionListener.onSensorChanged(null);
+        assertFalse(stationaryListener.isStationary);
+
+        // Since we're in quick doze, the device shouldn't stop idling.
+        verifyStateConditions(STATE_IDLE);
+
+        // Go to IDLE_MAINTENANCE
+        mDeviceIdleController.stepIdleStateLocked("testing");
+
+        mInjector.nowElapsed += mConstants.MOTION_INACTIVE_TIMEOUT / 2;
+
+        // Back to IDLE
+        mDeviceIdleController.stepIdleStateLocked("testing");
+
+        // Now enough time has passed.
+        mInjector.nowElapsed += mConstants.MOTION_INACTIVE_TIMEOUT / 2;
+        stationaryListener.motionExpected = false;
+        alarmListener.getValue().onAlarm();
+        assertTrue(stationaryListener.isStationary);
+    }
+
     private void enterDeepState(int state) {
         switch (state) {
             case STATE_ACTIVE:
@@ -1827,10 +1940,10 @@
     }
 
     private void setNetworkConnected(boolean connected) {
-        mInjector.connectivityService = mConnectivityService;
+        mInjector.connectivityManager = mConnectivityManager;
         final NetworkInfo ani = mock(NetworkInfo.class);
         doReturn(connected).when(ani).isConnected();
-        doReturn(ani).when(mConnectivityService).getActiveNetworkInfo();
+        doReturn(ani).when(mConnectivityManager).getActiveNetworkInfo();
         mDeviceIdleController.updateConnectivityState(null);
     }
 
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 1685b04..8b3c85e 100644
--- a/services/tests/mockingservicestests/src/com/android/server/am/MockingOomAdjusterTests.java
+++ b/services/tests/mockingservicestests/src/com/android/server/am/MockingOomAdjusterTests.java
@@ -82,6 +82,7 @@
 import android.os.IBinder;
 import android.os.PowerManagerInternal;
 import android.os.SystemClock;
+import android.platform.test.annotations.Presubmit;
 import android.util.ArrayMap;
 import android.util.ArraySet;
 import android.util.SparseArray;
@@ -103,6 +104,7 @@
  * Build/Install/Run:
  * atest MockingOomAdjusterTests
  */
+@Presubmit
 public class MockingOomAdjusterTests {
     private static final int MOCKAPP_PID = 12345;
     private static final int MOCKAPP_UID = 12345;
diff --git a/services/tests/mockingservicestests/src/com/android/server/display/color/DisplayWhiteBalanceTintControllerTest.java b/services/tests/mockingservicestests/src/com/android/server/display/color/DisplayWhiteBalanceTintControllerTest.java
index 4538cac..5c2b8ce 100644
--- a/services/tests/mockingservicestests/src/com/android/server/display/color/DisplayWhiteBalanceTintControllerTest.java
+++ b/services/tests/mockingservicestests/src/com/android/server/display/color/DisplayWhiteBalanceTintControllerTest.java
@@ -20,6 +20,8 @@
 
 import static com.google.common.truth.Truth.assertWithMessage;
 
+import static org.junit.Assert.assertArrayEquals;
+
 import android.content.Context;
 import android.content.res.Resources;
 import android.os.Binder;
@@ -184,8 +186,56 @@
                 .isFalse();
     }
 
+    /**
+     * Matrix should match the precalculated one for given cct and display primaries.
+     */
+    @Test
+    public void displayWhiteBalance_validateTransformMatrix() {
+        DisplayPrimaries displayPrimaries = new DisplayPrimaries();
+        displayPrimaries.red = new CieXyz();
+        displayPrimaries.red.X = 0.412315f;
+        displayPrimaries.red.Y = 0.212600f;
+        displayPrimaries.red.Z = 0.019327f;
+        displayPrimaries.green = new CieXyz();
+        displayPrimaries.green.X = 0.357600f;
+        displayPrimaries.green.Y = 0.715200f;
+        displayPrimaries.green.Z = 0.119200f;
+        displayPrimaries.blue = new CieXyz();
+        displayPrimaries.blue.X = 0.180500f;
+        displayPrimaries.blue.Y = 0.072200f;
+        displayPrimaries.blue.Z = 0.950633f;
+        displayPrimaries.white = new CieXyz();
+        displayPrimaries.white.X = 0.950456f;
+        displayPrimaries.white.Y = 1.000000f;
+        displayPrimaries.white.Z = 1.089058f;
+        doReturn(displayPrimaries)
+                .when(() -> SurfaceControl.getDisplayNativePrimaries(mDisplayToken));
+
+        setUpTintController();
+        assertWithMessage("Setup with valid SurfaceControl failed")
+                .that(mDisplayWhiteBalanceTintController.mSetUp)
+                .isTrue();
+
+        final int cct = 6500;
+        mDisplayWhiteBalanceTintController.setMatrix(cct);
+        assertWithMessage("Failed to set temperature")
+                .that(mDisplayWhiteBalanceTintController.mCurrentColorTemperature)
+                .isEqualTo(cct);
+
+        float[] matrixDwb = mDisplayWhiteBalanceTintController.getMatrix();
+        final float[] expectedMatrixDwb = {
+            0.962880f,  -0.001780f, -0.000158f, 0.0f,
+            0.035765f,   0.929988f,  0.000858f, 0.0f,
+            0.001354f,  -0.000470f,  0.948327f, 0.0f,
+            0.0f,        0.0f,       0.0f,      1.0f
+        };
+        assertArrayEquals("Unexpected DWB matrix", matrixDwb, expectedMatrixDwb,
+            1e-6f /* tolerance */);
+    }
+
     private void setUpTintController() {
         mDisplayWhiteBalanceTintController = new DisplayWhiteBalanceTintController();
         mDisplayWhiteBalanceTintController.setUp(mMockedContext, true);
+        mDisplayWhiteBalanceTintController.setActivated(true);
     }
 }
diff --git a/services/tests/servicestests/src/com/android/server/accessibility/AbstractAccessibilityServiceConnectionTest.java b/services/tests/servicestests/src/com/android/server/accessibility/AbstractAccessibilityServiceConnectionTest.java
index 73dcb98..d11d987 100644
--- a/services/tests/servicestests/src/com/android/server/accessibility/AbstractAccessibilityServiceConnectionTest.java
+++ b/services/tests/servicestests/src/com/android/server/accessibility/AbstractAccessibilityServiceConnectionTest.java
@@ -46,6 +46,7 @@
 import static org.hamcrest.Matchers.hasItems;
 import static org.hamcrest.Matchers.is;
 import static org.hamcrest.Matchers.nullValue;
+import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertThat;
 import static org.mockito.ArgumentMatchers.any;
 import static org.mockito.ArgumentMatchers.anyInt;
@@ -140,6 +141,8 @@
     private final List<AccessibilityWindowInfo> mA11yWindowInfosOnSecondDisplay = new ArrayList<>();
     private Callable[] mFindA11yNodesFunctions;
     private Callable<Boolean> mPerformA11yAction;
+    private ArrayList<Integer> mDisplayList = new ArrayList<>(Arrays.asList(
+            Display.DEFAULT_DISPLAY, SECONDARY_DISPLAY_ID));
 
     // To mock package-private class.
     @Rule public final DexmakerShareClassLoaderRule mDexmakerShareClassLoaderRule =
@@ -153,7 +156,7 @@
     @Mock private AccessibilityWindowManager mMockA11yWindowManager;
     @Mock private AbstractAccessibilityServiceConnection.SystemSupport mMockSystemSupport;
     @Mock private WindowManagerInternal mMockWindowManagerInternal;
-    @Mock private GlobalActionPerformer mMockGlobalActionPerformer;
+    @Mock private SystemActionPerformer mMockSystemActionPerformer;
     @Mock private IBinder mMockService;
     @Mock private IAccessibilityServiceClient mMockServiceInterface;
     @Mock private KeyEventDispatcher mMockKeyEventDispatcher;
@@ -184,6 +187,7 @@
         addA11yWindowInfo(mA11yWindowInfos, PIP_WINDOWID, true, Display.DEFAULT_DISPLAY);
         addA11yWindowInfo(mA11yWindowInfosOnSecondDisplay, WINDOWID_ONSECONDDISPLAY, false,
                 SECONDARY_DISPLAY_ID);
+        when(mMockA11yWindowManager.getDisplayListLocked()).thenReturn(mDisplayList);
         when(mMockA11yWindowManager.getWindowListLocked(Display.DEFAULT_DISPLAY))
                 .thenReturn(mA11yWindowInfos);
         when(mMockA11yWindowManager.findA11yWindowInfoByIdLocked(WINDOWID))
@@ -217,7 +221,7 @@
 
         mServiceConnection = new TestAccessibilityServiceConnection(mMockContext, COMPONENT_NAME,
                 mSpyServiceInfo, SERVICE_ID, mHandler, new Object(), mMockSecurityPolicy,
-                mMockSystemSupport, mMockWindowManagerInternal, mMockGlobalActionPerformer,
+                mMockSystemSupport, mMockWindowManagerInternal, mMockSystemActionPerformer,
                 mMockA11yWindowManager);
         // Assume that the service is connected
         mServiceConnection.mService = mMockService;
@@ -285,7 +289,14 @@
 
     @Test
     public void getWindows() {
-        assertThat(mServiceConnection.getWindows(), is(mA11yWindowInfos));
+        final AccessibilityWindowInfo.WindowListSparseArray allWindows =
+                mServiceConnection.getWindows();
+
+        assertEquals(2, allWindows.size());
+        assertThat(allWindows.get(Display.DEFAULT_DISPLAY), is(mA11yWindowInfos));
+        assertEquals(2, allWindows.get(Display.DEFAULT_DISPLAY).size());
+        assertThat(allWindows.get(SECONDARY_DISPLAY_ID), is(mA11yWindowInfosOnSecondDisplay));
+        assertEquals(1, allWindows.get(SECONDARY_DISPLAY_ID).size());
     }
 
     @Test
@@ -478,7 +489,7 @@
     @Test
     public void performGlobalAction() {
         mServiceConnection.performGlobalAction(GLOBAL_ACTION_HOME);
-        verify(mMockGlobalActionPerformer).performGlobalAction(GLOBAL_ACTION_HOME);
+        verify(mMockSystemActionPerformer).performSystemAction(GLOBAL_ACTION_HOME);
     }
 
     @Test
@@ -765,10 +776,10 @@
                 AccessibilityServiceInfo accessibilityServiceInfo, int id, Handler mainHandler,
                 Object lock, AccessibilitySecurityPolicy securityPolicy,
                 SystemSupport systemSupport, WindowManagerInternal windowManagerInternal,
-                GlobalActionPerformer globalActionPerfomer,
+                SystemActionPerformer systemActionPerfomer,
                 AccessibilityWindowManager a11yWindowManager) {
             super(context, componentName, accessibilityServiceInfo, id, mainHandler, lock,
-                    securityPolicy, systemSupport, windowManagerInternal, globalActionPerfomer,
+                    securityPolicy, systemSupport, windowManagerInternal, systemActionPerfomer,
                     a11yWindowManager);
             mResolvedUserId = USER_ID;
         }
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 6be5a37..edf82ee 100644
--- a/services/tests/servicestests/src/com/android/server/accessibility/AccessibilityServiceConnectionTest.java
+++ b/services/tests/servicestests/src/com/android/server/accessibility/AccessibilityServiceConnectionTest.java
@@ -75,7 +75,7 @@
     @Mock AccessibilityWindowManager mMockA11yWindowManager;
     @Mock AbstractAccessibilityServiceConnection.SystemSupport mMockSystemSupport;
     @Mock WindowManagerInternal mMockWindowManagerInternal;
-    @Mock GlobalActionPerformer mMockGlobalActionPerformer;
+    @Mock SystemActionPerformer mMockSystemActionPerformer;
     @Mock KeyEventDispatcher mMockKeyEventDispatcher;
     @Mock MagnificationController mMockMagnificationController;
     @Mock IBinder mMockIBinder;
@@ -104,7 +104,7 @@
         mConnection = new AccessibilityServiceConnection(mMockUserState, mMockContext,
                 COMPONENT_NAME, mMockServiceInfo, SERVICE_ID, mHandler, new Object(),
                 mMockSecurityPolicy, mMockSystemSupport, mMockWindowManagerInternal,
-                mMockGlobalActionPerformer, mMockA11yWindowManager);
+                mMockSystemActionPerformer, mMockA11yWindowManager);
         when(mMockSecurityPolicy.canPerformGestures(mConnection)).thenReturn(true);
     }
 
diff --git a/services/tests/servicestests/src/com/android/server/accessibility/AccessibilityWindowManagerTest.java b/services/tests/servicestests/src/com/android/server/accessibility/AccessibilityWindowManagerTest.java
index b7b5a4e..b5e5deb 100644
--- a/services/tests/servicestests/src/com/android/server/accessibility/AccessibilityWindowManagerTest.java
+++ b/services/tests/servicestests/src/com/android/server/accessibility/AccessibilityWindowManagerTest.java
@@ -67,6 +67,7 @@
 import org.mockito.MockitoAnnotations;
 
 import java.util.ArrayList;
+import java.util.Arrays;
 import java.util.List;
 
 /**
@@ -104,6 +105,9 @@
     // List of callback, mapping from displayId -> callback.
     private final SparseArray<WindowsForAccessibilityCallback> mCallbackOfWindows =
             new SparseArray<>();
+    // List of display ID.
+    private final ArrayList<Integer> mExpectedDisplayList = new ArrayList<>(Arrays.asList(
+            Display.DEFAULT_DISPLAY, SECONDARY_DISPLAY_ID));
 
     private final MessageCapturingHandler mHandler = new MessageCapturingHandler(null);
 
@@ -692,6 +696,15 @@
         assertTrue(windowId >= 0);
     }
 
+    @Test
+    public void getDisplayList() throws RemoteException {
+        // Starts tracking window of second display.
+        startTrackingPerDisplay(SECONDARY_DISPLAY_ID);
+
+        final ArrayList<Integer> displayList = mA11yWindowManager.getDisplayListLocked();
+        assertTrue(displayList.equals(mExpectedDisplayList));
+    }
+
     private void startTrackingPerDisplay(int displayId) throws RemoteException {
         ArrayList<WindowInfo> windowInfosForDisplay = new ArrayList<>();
         // Adds RemoteAccessibilityConnection into AccessibilityWindowManager, and copy
diff --git a/services/tests/servicestests/src/com/android/server/accessibility/GlobalActionPerformerTest.java b/services/tests/servicestests/src/com/android/server/accessibility/SystemActionPerformerTest.java
similarity index 63%
rename from services/tests/servicestests/src/com/android/server/accessibility/GlobalActionPerformerTest.java
rename to services/tests/servicestests/src/com/android/server/accessibility/SystemActionPerformerTest.java
index c73be6f..37f5b87 100644
--- a/services/tests/servicestests/src/com/android/server/accessibility/GlobalActionPerformerTest.java
+++ b/services/tests/servicestests/src/com/android/server/accessibility/SystemActionPerformerTest.java
@@ -1,17 +1,17 @@
 /*
- ** Copyright 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.
+ * 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.accessibility;
@@ -35,13 +35,11 @@
 import org.mockito.Mock;
 import org.mockito.MockitoAnnotations;
 
-import java.util.function.Consumer;
-
 /**
- * Tests for GlobalActionPerformer
+ * Tests for SystemActionPerformer
  */
-public class GlobalActionPerformerTest {
-    GlobalActionPerformer mGlobalActionPerformer;
+public class SystemActionPerformerTest {
+    SystemActionPerformer mSystemActionPerformer;
 
     @Mock Context mMockContext;
     @Mock WindowManagerInternal mMockWindowManagerInternal;
@@ -55,34 +53,34 @@
         when(mMockContext.getSystemService(android.app.Service.STATUS_BAR_SERVICE))
                 .thenReturn(mMockStatusBarManager);
 
-        mGlobalActionPerformer =
-                new GlobalActionPerformer(mMockContext, mMockWindowManagerInternal,
+        mSystemActionPerformer =
+                new SystemActionPerformer(mMockContext, mMockWindowManagerInternal,
                         () -> mMockScreenshotHelper);
     }
 
     @Test
     public void testNotifications_expandsNotificationPanel() {
-        mGlobalActionPerformer
-                .performGlobalAction(AccessibilityService.GLOBAL_ACTION_NOTIFICATIONS);
+        mSystemActionPerformer
+                .performSystemAction(AccessibilityService.GLOBAL_ACTION_NOTIFICATIONS);
         verify(mMockStatusBarManager).expandNotificationsPanel();
     }
 
     @Test
     public void testQuickSettings_requestsQuickSettingsPanel() {
-        mGlobalActionPerformer
-                .performGlobalAction(AccessibilityService.GLOBAL_ACTION_QUICK_SETTINGS);
+        mSystemActionPerformer
+                .performSystemAction(AccessibilityService.GLOBAL_ACTION_QUICK_SETTINGS);
         verify(mMockStatusBarManager).expandSettingsPanel();
     }
 
     @Test
     public void testPowerDialog_requestsFromWindowManager() {
-        mGlobalActionPerformer.performGlobalAction(AccessibilityService.GLOBAL_ACTION_POWER_DIALOG);
+        mSystemActionPerformer.performSystemAction(AccessibilityService.GLOBAL_ACTION_POWER_DIALOG);
         verify(mMockWindowManagerInternal).showGlobalActions();
     }
 
     @Test
     public void testScreenshot_requestsFromScreenshotHelper() {
-        mGlobalActionPerformer.performGlobalAction(
+        mSystemActionPerformer.performSystemAction(
                 AccessibilityService.GLOBAL_ACTION_TAKE_SCREENSHOT);
         verify(mMockScreenshotHelper).takeScreenshot(
                 eq(android.view.WindowManager.TAKE_SCREENSHOT_FULLSCREEN), anyBoolean(),
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 210de53..deb6f71 100644
--- a/services/tests/servicestests/src/com/android/server/accessibility/UiAutomationManagerTest.java
+++ b/services/tests/servicestests/src/com/android/server/accessibility/UiAutomationManagerTest.java
@@ -64,7 +64,7 @@
     @Mock AccessibilityWindowManager mMockA11yWindowManager;
     @Mock AbstractAccessibilityServiceConnection.SystemSupport mMockSystemSupport;
     @Mock WindowManagerInternal mMockWindowManagerInternal;
-    @Mock GlobalActionPerformer mMockGlobalActionPerformer;
+    @Mock SystemActionPerformer mMockSystemActionPerformer;
     @Mock IBinder mMockOwner;
     @Mock IAccessibilityServiceClient mMockAccessibilityServiceClient;
     @Mock IBinder mMockServiceAsBinder;
@@ -174,7 +174,7 @@
         mUiAutomationManager.registerUiTestAutomationServiceLocked(mMockOwner,
                 mMockAccessibilityServiceClient, mMockContext, mMockServiceInfo, SERVICE_ID,
                 mMessageCapturingHandler, mMockSecurityPolicy, mMockSystemSupport,
-                mMockWindowManagerInternal, mMockGlobalActionPerformer,
+                mMockWindowManagerInternal, mMockSystemActionPerformer,
                 mMockA11yWindowManager, flags);
     }
 
diff --git a/services/tests/servicestests/src/com/android/server/am/UserControllerTest.java b/services/tests/servicestests/src/com/android/server/am/UserControllerTest.java
index d4b7e7e9..79cc3db 100644
--- a/services/tests/servicestests/src/com/android/server/am/UserControllerTest.java
+++ b/services/tests/servicestests/src/com/android/server/am/UserControllerTest.java
@@ -25,8 +25,8 @@
 import static com.android.server.am.UserController.REPORT_LOCKED_BOOT_COMPLETE_MSG;
 import static com.android.server.am.UserController.REPORT_USER_SWITCH_COMPLETE_MSG;
 import static com.android.server.am.UserController.REPORT_USER_SWITCH_MSG;
-import static com.android.server.am.UserController.SYSTEM_USER_CURRENT_MSG;
-import static com.android.server.am.UserController.SYSTEM_USER_START_MSG;
+import static com.android.server.am.UserController.USER_CURRENT_MSG;
+import static com.android.server.am.UserController.USER_START_MSG;
 import static com.android.server.am.UserController.USER_SWITCH_TIMEOUT_MSG;
 
 import static com.google.android.collect.Lists.newArrayList;
@@ -53,11 +53,13 @@
 import static org.mockito.Mockito.verify;
 import static org.mockito.Mockito.when;
 
+import android.annotation.UserIdInt;
 import android.app.IUserSwitchObserver;
 import android.content.Context;
 import android.content.IIntentReceiver;
 import android.content.Intent;
 import android.content.pm.UserInfo;
+import android.content.pm.UserInfo.UserInfoFlag;
 import android.os.Binder;
 import android.os.Bundle;
 import android.os.Handler;
@@ -106,6 +108,10 @@
     private static final int TEST_USER_ID1 = 101;
     private static final int TEST_USER_ID2 = 102;
     private static final int NONEXIST_USER_ID = 2;
+    private static final int TEST_PRE_CREATED_USER_ID = 103;
+
+    private static final int NO_USERINFO_FLAGS = 0;
+
     private static final String TAG = UserControllerTest.class.getSimpleName();
 
     private static final long HANDLER_WAIT_TIME_MS = 100;
@@ -127,11 +133,11 @@
     private static final Set<Integer> START_FOREGROUND_USER_MESSAGE_CODES = newHashSet(
             REPORT_USER_SWITCH_MSG,
             USER_SWITCH_TIMEOUT_MSG,
-            SYSTEM_USER_START_MSG,
-            SYSTEM_USER_CURRENT_MSG);
+            USER_START_MSG,
+            USER_CURRENT_MSG);
 
     private static final Set<Integer> START_BACKGROUND_USER_MESSAGE_CODES = newHashSet(
-            SYSTEM_USER_START_MSG,
+            USER_START_MSG,
             REPORT_LOCKED_BOOT_COMPLETE_MSG);
 
     @Before
@@ -148,7 +154,8 @@
             doNothing().when(mInjector).clearBroadcastQueueForUser(anyInt());
             doNothing().when(mInjector).stackSupervisorRemoveUser(anyInt());
             mUserController = new UserController(mInjector);
-            setUpUser(TEST_USER_ID, 0);
+            setUpUser(TEST_USER_ID, NO_USERINFO_FLAGS);
+            setUpUser(TEST_PRE_CREATED_USER_ID, NO_USERINFO_FLAGS, /* preCreated=*/ true);
         });
     }
 
@@ -188,6 +195,31 @@
         startForegroundUserAssertions();
     }
 
+    @Test
+    public void testStartPreCreatedUser_foreground() {
+        assertFalse(mUserController.startUser(TEST_PRE_CREATED_USER_ID, /* foreground= */ true));
+    }
+
+    @Test
+    public void testStartPreCreatedUser_background() throws Exception {
+        assertTrue(mUserController.startUser(TEST_PRE_CREATED_USER_ID, /* foreground= */ false));
+
+        verify(mInjector.getWindowManager(), never()).startFreezingScreen(anyInt(), anyInt());
+        verify(mInjector.getWindowManager(), never()).setSwitchingUser(anyBoolean());
+        verify(mInjector, never()).clearAllLockedTasks(anyString());
+
+        assertWithMessage("should not have received intents")
+                .that(getActions(mInjector.mSentIntents)).isEmpty();
+        // TODO(b/140868593): should have received a USER_UNLOCK_MSG message as well, but it doesn't
+        // because StorageManager.isUserKeyUnlocked(TEST_PRE_CREATED_USER_ID) returns false - to
+        // properly fix it, we'd need to move this class to FrameworksMockingServicesTests so we can
+        // mock static methods (but moving this class would involve changing the presubmit tests,
+        // and the cascade effect goes on...). In fact, a better approach would to not assert the
+        // binder calls, but their side effects (in this case, that the user is stopped right away)
+        assertWithMessage("wrong binder message calls").that(mInjector.mHandler.getMessageCodes())
+                .containsExactly(USER_START_MSG);
+    }
+
     private void startUserAssertions(
             List<String> expectedActions, Set<Integer> expectedMessageCodes) {
         assertEquals(expectedActions, getActions(mInjector.mSentIntents));
@@ -467,9 +499,15 @@
         continueUserSwitchAssertions(newUserId, expectOldUserStopping);
     }
 
-    private void setUpUser(int userId, int flags) {
+    private void setUpUser(@UserIdInt int userId, @UserInfoFlag int flags) {
+        setUpUser(userId, flags, /* preCreated= */ false);
+    }
+
+    private void setUpUser(@UserIdInt int userId, @UserInfoFlag int flags, boolean preCreated) {
         UserInfo userInfo = new UserInfo(userId, "User" + userId, flags);
+        userInfo.preCreated = preCreated;
         when(mInjector.mUserManagerMock.getUserInfo(eq(userId))).thenReturn(userInfo);
+        when(mInjector.mUserManagerMock.isPreCreated(userId)).thenReturn(preCreated);
     }
 
     private static List<String> getActions(List<Intent> intents) {
diff --git a/services/tests/servicestests/src/com/android/server/biometrics/BiometricServiceTest.java b/services/tests/servicestests/src/com/android/server/biometrics/BiometricServiceTest.java
index ccf3a90..4aeeb0a 100644
--- a/services/tests/servicestests/src/com/android/server/biometrics/BiometricServiceTest.java
+++ b/services/tests/servicestests/src/com/android/server/biometrics/BiometricServiceTest.java
@@ -39,6 +39,7 @@
 import android.content.Context;
 import android.content.pm.PackageManager;
 import android.content.res.Resources;
+import android.hardware.biometrics.Authenticator;
 import android.hardware.biometrics.BiometricAuthenticator;
 import android.hardware.biometrics.BiometricConstants;
 import android.hardware.biometrics.BiometricPrompt;
@@ -55,6 +56,9 @@
 import android.os.IBinder;
 import android.security.KeyStore;
 
+import androidx.test.InstrumentationRegistry;
+import androidx.test.filters.SmallTest;
+
 import com.android.internal.R;
 import com.android.internal.statusbar.IStatusBarService;
 
@@ -66,9 +70,6 @@
 
 import java.util.List;
 
-import androidx.test.InstrumentationRegistry;
-import androidx.test.filters.SmallTest;
-
 @SmallTest
 public class BiometricServiceTest {
 
@@ -82,6 +83,7 @@
     private static final String ERROR_CANCELED = "error_canceled";
     private static final String ERROR_UNABLE_TO_PROCESS = "error_unable_to_process";
     private static final String ERROR_USER_CANCELED = "error_user_canceled";
+    private static final String ERROR_LOCKOUT = "error_lockout";
 
     private static final String FINGERPRINT_ACQUIRED_SENSOR_DIRTY = "sensor_dirty";
 
@@ -179,7 +181,8 @@
         mBiometricService = new BiometricService(mContext, new MockInjector());
         mBiometricService.onStart();
 
-        invokeAuthenticate(mBiometricService.mImpl, mReceiver1, false /* requireConfirmation */);
+        invokeAuthenticate(mBiometricService.mImpl, mReceiver1, false /* requireConfirmation */,
+                false /* allowDeviceCredential */);
         waitForIdle();
         verify(mReceiver1).onError(
                 eq(BiometricConstants.BIOMETRIC_ERROR_HW_NOT_PRESENT), eq(ERROR_HW_UNAVAILABLE));
@@ -193,7 +196,8 @@
         mBiometricService = new BiometricService(mContext, new MockInjector());
         mBiometricService.onStart();
 
-        invokeAuthenticate(mBiometricService.mImpl, mReceiver1, false /* requireConfirmation */);
+        invokeAuthenticate(mBiometricService.mImpl, mReceiver1, false /* requireConfirmation */,
+                false /* allowDeviceCredential */);
         waitForIdle();
         verify(mReceiver1).onError(
                 eq(BiometricConstants.BIOMETRIC_ERROR_NO_BIOMETRICS), any());
@@ -208,7 +212,8 @@
         mBiometricService = new BiometricService(mContext, new MockInjector());
         mBiometricService.onStart();
 
-        invokeAuthenticate(mBiometricService.mImpl, mReceiver1, false /* requireConfirmation */);
+        invokeAuthenticate(mBiometricService.mImpl, mReceiver1, false /* requireConfirmation */,
+                false /* allowDeviceCredential */);
         waitForIdle();
         verify(mReceiver1).onError(
                 eq(BiometricConstants.BIOMETRIC_ERROR_HW_UNAVAILABLE), eq(ERROR_HW_UNAVAILABLE));
@@ -226,7 +231,8 @@
 
         // Disabled in user settings receives onError
         when(mBiometricService.mSettingObserver.getFaceEnabledForApps(anyInt())).thenReturn(false);
-        invokeAuthenticate(mBiometricService.mImpl, mReceiver1, false /* requireConfirmation */);
+        invokeAuthenticate(mBiometricService.mImpl, mReceiver1, false /* requireConfirmation */,
+                false /* allowDeviceCredential */);
         waitForIdle();
         verify(mReceiver1).onError(
                 eq(BiometricConstants.BIOMETRIC_ERROR_HW_UNAVAILABLE), eq(ERROR_HW_UNAVAILABLE));
@@ -236,7 +242,8 @@
         when(mBiometricService.mSettingObserver.getFaceEnabledForApps(anyInt())).thenReturn(true);
         when(mBiometricService.mSettingObserver.getFaceAlwaysRequireConfirmation(anyInt()))
                 .thenReturn(true);
-        invokeAuthenticate(mBiometricService.mImpl, mReceiver1, false /* requireConfirmation */);
+        invokeAuthenticate(mBiometricService.mImpl, mReceiver1, false /* requireConfirmation */,
+                false /* allowDeviceCredential */);
         waitForIdle();
         verify(mReceiver1, never()).onError(anyInt(), any(String.class));
         verify(mBiometricService.mFaceService).prepareForAuthentication(
@@ -255,7 +262,8 @@
         resetReceiver();
         when(mBiometricService.mSettingObserver.getFaceAlwaysRequireConfirmation(anyInt()))
                 .thenReturn(false);
-        invokeAuthenticate(mBiometricService.mImpl, mReceiver1, false /* requireConfirmation */);
+        invokeAuthenticate(mBiometricService.mImpl, mReceiver1, false /* requireConfirmation */,
+                false /* allowDeviceCredential */);
         waitForIdle();
         verify(mBiometricService.mFaceService).prepareForAuthentication(
                 eq(false) /* requireConfirmation */,
@@ -277,7 +285,8 @@
         mBiometricService.onStart();
 
         // Start testing the happy path
-        invokeAuthenticate(mBiometricService.mImpl, mReceiver1, false /* requireConfirmation */);
+        invokeAuthenticate(mBiometricService.mImpl, mReceiver1, false /* requireConfirmation */,
+                false /* allowDeviceCredential */);
         waitForIdle();
 
         // Creates a pending auth session with the correct initial states
@@ -311,7 +320,7 @@
                 .startPreparedClient(cookieCaptor.getValue());
 
         // StatusBar showBiometricDialog invoked
-        verify(mBiometricService.mStatusBarService).showBiometricDialog(
+        verify(mBiometricService.mStatusBarService).showAuthenticationDialog(
                 eq(mBiometricService.mCurrentAuthSession.mBundle),
                 any(IBiometricServiceReceiverInternal.class),
                 eq(BiometricAuthenticator.TYPE_FINGERPRINT),
@@ -333,7 +342,7 @@
 
         // SystemUI sends callback with dismissed reason
         mBiometricService.mInternalReceiver.onDialogDismissed(
-                BiometricPrompt.DISMISSED_REASON_CONFIRM_NOT_REQUIRED);
+                BiometricPrompt.DISMISSED_REASON_BIOMETRIC_CONFIRM_NOT_REQUIRED);
         waitForIdle();
         // HAT sent to keystore
         verify(mBiometricService.mKeyStore).addAuthToken(any(byte[].class));
@@ -344,10 +353,32 @@
     }
 
     @Test
+    public void testAuthenticate_noBiometrics_credentialAllowed() throws Exception {
+        setupAuthForOnly(BiometricAuthenticator.TYPE_FACE);
+        when(mFaceManager.hasEnrolledTemplates(anyInt())).thenReturn(false);
+        invokeAuthenticate(mBiometricService.mImpl, mReceiver1,
+                true /* requireConfirmation */, true /* allowDeviceCredential */);
+        waitForIdle();
+
+        assertEquals(BiometricService.STATE_SHOWING_DEVICE_CREDENTIAL,
+                mBiometricService.mCurrentAuthSession.mState);
+        assertEquals(Authenticator.TYPE_CREDENTIAL,
+                mBiometricService.mCurrentAuthSession.mBundle
+                        .getInt(BiometricPrompt.KEY_AUTHENTICATORS_ALLOWED));
+        verify(mBiometricService.mStatusBarService).showAuthenticationDialog(
+                eq(mBiometricService.mCurrentAuthSession.mBundle),
+                any(IBiometricServiceReceiverInternal.class),
+                eq(0 /* biometricModality */),
+                anyBoolean() /* requireConfirmation */,
+                anyInt() /* userId */,
+                eq(TEST_PACKAGE_NAME));
+    }
+
+    @Test
     public void testAuthenticate_happyPathWithConfirmation() throws Exception {
         setupAuthForOnly(BiometricAuthenticator.TYPE_FACE);
         invokeAuthenticateAndStart(mBiometricService.mImpl, mReceiver1,
-                true /* requireConfirmation */);
+                true /* requireConfirmation */, false /* allowDeviceCredential */);
 
         // Test authentication succeeded goes to PENDING_CONFIRMATION and that the HAT is not
         // sent to KeyStore yet
@@ -362,7 +393,7 @@
 
         // SystemUI sends confirm, HAT is sent to keystore and client is notified.
         mBiometricService.mInternalReceiver.onDialogDismissed(
-                BiometricPrompt.DISMISSED_REASON_CONFIRMED);
+                BiometricPrompt.DISMISSED_REASON_BIOMETRIC_CONFIRMED);
         waitForIdle();
         verify(mBiometricService.mKeyStore).addAuthToken(any(byte[].class));
         verify(mReceiver1).onAuthenticationSucceeded();
@@ -373,7 +404,7 @@
             throws Exception {
         setupAuthForOnly(BiometricAuthenticator.TYPE_FACE);
         invokeAuthenticateAndStart(mBiometricService.mImpl, mReceiver1,
-                false /* requireConfirmation */);
+                false /* requireConfirmation */, false /* allowDeviceCredential */);
 
         mBiometricService.mInternalReceiver.onAuthenticationFailed();
         waitForIdle();
@@ -390,7 +421,7 @@
             throws Exception {
         setupAuthForOnly(BiometricAuthenticator.TYPE_FINGERPRINT);
         invokeAuthenticateAndStart(mBiometricService.mImpl, mReceiver1,
-                false /* requireConfirmation */);
+                false /* requireConfirmation */, false /* allowDeviceCredential */);
 
         mBiometricService.mInternalReceiver.onAuthenticationFailed();
         waitForIdle();
@@ -406,13 +437,14 @@
     public void testErrorCanceled_whenAuthenticating_notifiesSystemUIAndClient() throws Exception {
         setupAuthForOnly(BiometricAuthenticator.TYPE_FINGERPRINT);
         invokeAuthenticateAndStart(mBiometricService.mImpl, mReceiver1,
-                false /* requireConfirmation */);
+                false /* requireConfirmation */, false /* allowDeviceCredential */);
 
         // Create a new pending auth session but don't start it yet. HAL contract is that previous
         // one must get ERROR_CANCELED. Simulate that here by creating the pending auth session,
         // sending ERROR_CANCELED to the current auth session, and then having the second one
         // onReadyForAuthentication.
-        invokeAuthenticate(mBiometricService.mImpl, mReceiver2, false /* requireConfirmation */);
+        invokeAuthenticate(mBiometricService.mImpl, mReceiver2, false /* requireConfirmation */,
+                false /* allowDeviceCredential */);
         waitForIdle();
 
         assertEquals(mBiometricService.mCurrentAuthSession.mState,
@@ -430,7 +462,7 @@
         verify(mReceiver2, never()).onError(anyInt(), any(String.class));
 
         // SystemUI dialog closed
-        verify(mBiometricService.mStatusBarService).hideBiometricDialog();
+        verify(mBiometricService.mStatusBarService).hideAuthenticationDialog();
 
         // After SystemUI notifies that the animation has completed
         mBiometricService.mInternalReceiver
@@ -446,7 +478,7 @@
     public void testErrorHalTimeout_whenAuthenticating_entersPausedState() throws Exception {
         setupAuthForOnly(BiometricAuthenticator.TYPE_FACE);
         invokeAuthenticateAndStart(mBiometricService.mImpl, mReceiver1,
-                false /* requireConfirmation */);
+                false /* requireConfirmation */, false /* allowDeviceCredential */);
 
         mBiometricService.mInternalReceiver.onError(
                 getCookieForCurrentSession(mBiometricService.mCurrentAuthSession),
@@ -479,7 +511,7 @@
         resetStatusBar();
         startPendingAuthSession(mBiometricService);
         waitForIdle();
-        verify(mBiometricService.mStatusBarService, never()).showBiometricDialog(
+        verify(mBiometricService.mStatusBarService, never()).showAuthenticationDialog(
                 any(Bundle.class),
                 any(IBiometricServiceReceiverInternal.class),
                 anyInt(),
@@ -492,7 +524,7 @@
     public void testErrorFromHal_whenPaused_notifiesSystemUIAndClient() throws Exception {
         setupAuthForOnly(BiometricAuthenticator.TYPE_FACE);
         invokeAuthenticateAndStart(mBiometricService.mImpl, mReceiver1,
-                false /* requireCOnfirmation */);
+                false /* requireCOnfirmation */, false /* allowDeviceCredential */);
 
         mBiometricService.mInternalReceiver.onError(
                 getCookieForCurrentSession(mBiometricService.mCurrentAuthSession),
@@ -509,7 +541,7 @@
                 eq(BiometricConstants.BIOMETRIC_ERROR_CANCELED),
                 eq(ERROR_CANCELED));
         // Dialog is hidden immediately
-        verify(mBiometricService.mStatusBarService).hideBiometricDialog();
+        verify(mBiometricService.mStatusBarService).hideAuthenticationDialog();
         // Auth session is over
         assertNull(mBiometricService.mCurrentAuthSession);
     }
@@ -522,7 +554,7 @@
         // session is done.
         setupAuthForOnly(BiometricAuthenticator.TYPE_FINGERPRINT);
         invokeAuthenticateAndStart(mBiometricService.mImpl, mReceiver1,
-                false /* requireConfirmation */);
+                false /* requireConfirmation */, false /* allowDeviceCredential */);
 
         mBiometricService.mInternalReceiver.onError(
                 getCookieForCurrentSession(mBiometricService.mCurrentAuthSession),
@@ -533,9 +565,10 @@
         // Sends error to SystemUI and does not notify client yet
         assertEquals(mBiometricService.mCurrentAuthSession.mState,
                 BiometricService.STATE_ERROR_PENDING_SYSUI);
-        verify(mBiometricService.mStatusBarService)
-                .onBiometricError(eq(ERROR_UNABLE_TO_PROCESS));
-        verify(mBiometricService.mStatusBarService, never()).hideBiometricDialog();
+        verify(mBiometricService.mStatusBarService).onBiometricError(
+                eq(BiometricConstants.BIOMETRIC_ERROR_UNABLE_TO_PROCESS),
+                eq(ERROR_UNABLE_TO_PROCESS));
+        verify(mBiometricService.mStatusBarService, never()).hideAuthenticationDialog();
         verify(mReceiver1, never()).onError(anyInt(), anyString());
 
         // SystemUI animation completed, client is notified, auth session is over
@@ -549,11 +582,177 @@
     }
 
     @Test
+    public void testErrorFromHal_whilePreparingAuthentication_credentialAllowed() throws Exception {
+        setupAuthForOnly(BiometricAuthenticator.TYPE_FINGERPRINT);
+        invokeAuthenticate(mBiometricService.mImpl, mReceiver1,
+                false /* requireConfirmation */, true /* allowDeviceCredential */);
+        waitForIdle();
+
+        mBiometricService.mInternalReceiver.onError(
+                getCookieForPendingSession(mBiometricService.mPendingAuthSession),
+                BiometricConstants.BIOMETRIC_ERROR_LOCKOUT,
+                ERROR_LOCKOUT);
+        waitForIdle();
+
+        // Pending auth session becomes current auth session, since device credential should
+        // be shown now.
+        assertNull(mBiometricService.mPendingAuthSession);
+        assertNotNull(mBiometricService.mCurrentAuthSession);
+        assertEquals(BiometricService.STATE_SHOWING_DEVICE_CREDENTIAL,
+                mBiometricService.mCurrentAuthSession.mState);
+        assertEquals(Authenticator.TYPE_CREDENTIAL,
+                mBiometricService.mCurrentAuthSession.mBundle.getInt(
+                        BiometricPrompt.KEY_AUTHENTICATORS_ALLOWED));
+        verify(mBiometricService.mStatusBarService).showAuthenticationDialog(
+                eq(mBiometricService.mCurrentAuthSession.mBundle),
+                any(IBiometricServiceReceiverInternal.class),
+                eq(0 /* biometricModality */),
+                anyBoolean() /* requireConfirmation */,
+                anyInt() /* userId */,
+                eq(TEST_PACKAGE_NAME));
+    }
+
+    @Test
+    public void testErrorFromHal_whilePreparingAuthentication_credentialNotAllowed()
+            throws Exception {
+        setupAuthForOnly(BiometricAuthenticator.TYPE_FINGERPRINT);
+        invokeAuthenticate(mBiometricService.mImpl, mReceiver1,
+                false /* requireConfirmation */, false /* allowDeviceCredential */);
+        waitForIdle();
+
+        mBiometricService.mInternalReceiver.onError(
+                getCookieForPendingSession(mBiometricService.mPendingAuthSession),
+                BiometricConstants.BIOMETRIC_ERROR_LOCKOUT,
+                ERROR_LOCKOUT);
+        waitForIdle();
+
+        // Error is sent to client
+        assertNull(mBiometricService.mPendingAuthSession);
+        assertNull(mBiometricService.mCurrentAuthSession);
+    }
+
+    @Test
+    public void testCombineAuthenticatorBundle_keyAllowDeviceCredentialAlwaysRemoved() {
+        Bundle bundle;
+        int authenticators;
+
+        // In:
+        // KEY_ALLOW_DEVICE_CREDENTIAL = true
+        // KEY_AUTHENTICATORS_ALLOWED = TYPE_BIOMETRIC | TYPE_CREDENTIAL
+        // Out:
+        // KEY_ALLOW_DEVICE_CREDENTIAL = null
+        // KEY_AUTHENTICATORS_ALLOWED = TYPE_BIOMETRIC | TYPE_CREDENTIAL
+        bundle = new Bundle();
+        bundle.putBoolean(BiometricPrompt.KEY_ALLOW_DEVICE_CREDENTIAL, true);
+        authenticators = Authenticator.TYPE_CREDENTIAL | Authenticator.TYPE_BIOMETRIC;
+        bundle.putInt(BiometricPrompt.KEY_AUTHENTICATORS_ALLOWED, authenticators);
+        Utils.combineAuthenticatorBundles(bundle);
+        assertNull(bundle.get(BiometricPrompt.KEY_ALLOW_DEVICE_CREDENTIAL));
+        assertEquals(authenticators, bundle.getInt(BiometricPrompt.KEY_AUTHENTICATORS_ALLOWED));
+
+        // In:
+        // KEY_ALLOW_DEVICE_CREDENTIAL = true
+        // KEY_AUTHENTICATORS_ALLOWED = TYPE_BIOMETRIC
+        // Out:
+        // KEY_ALLOW_DEVICE_CREDENTIAL = null
+        // KEY_AUTHENTICATORS_ALLOWED = TYPE_BIOMETRIC | TYPE_CREDENTIAL
+        bundle = new Bundle();
+        bundle.putBoolean(BiometricPrompt.KEY_ALLOW_DEVICE_CREDENTIAL, true);
+        authenticators = Authenticator.TYPE_BIOMETRIC;
+        bundle.putInt(BiometricPrompt.KEY_AUTHENTICATORS_ALLOWED, authenticators);
+        Utils.combineAuthenticatorBundles(bundle);
+        assertNull(bundle.get(BiometricPrompt.KEY_ALLOW_DEVICE_CREDENTIAL));
+        assertEquals(authenticators, bundle.getInt(BiometricPrompt.KEY_AUTHENTICATORS_ALLOWED));
+
+        // In:
+        // KEY_ALLOW_DEVICE_CREDENTIAL = null
+        // KEY_AUTHENTICATORS_ALLOWED = TYPE_BIOMETRIC | TYPE_CREDENTIAL
+        // Out:
+        // KEY_ALLOW_DEVICE_CREDENTIAL = null
+        // KEY_AUTHENTICATORS_ALLOWED = TYPE_BIOMETRIC | TYPE_CREDENTIAL
+        bundle = new Bundle();
+        authenticators = Authenticator.TYPE_BIOMETRIC | Authenticator.TYPE_CREDENTIAL;
+        bundle.putInt(BiometricPrompt.KEY_AUTHENTICATORS_ALLOWED, authenticators);
+        Utils.combineAuthenticatorBundles(bundle);
+        assertNull(bundle.get(BiometricPrompt.KEY_ALLOW_DEVICE_CREDENTIAL));
+        assertEquals(authenticators, bundle.getInt(BiometricPrompt.KEY_AUTHENTICATORS_ALLOWED));
+    }
+
+    @Test
+    public void testErrorFromHal_whileShowingDeviceCredential_doesntNotifySystemUI()
+            throws Exception {
+        setupAuthForOnly(BiometricAuthenticator.TYPE_FINGERPRINT);
+        invokeAuthenticateAndStart(mBiometricService.mImpl, mReceiver1,
+                false /* requireConfirmation */, true /* allowDeviceCredential */);
+
+        mBiometricService.mInternalReceiver.onDeviceCredentialPressed();
+        waitForIdle();
+
+        assertEquals(BiometricService.STATE_SHOWING_DEVICE_CREDENTIAL,
+                mBiometricService.mCurrentAuthSession.mState);
+        verify(mReceiver1, never()).onError(anyInt(), anyString());
+
+        mBiometricService.mInternalReceiver.onError(
+                getCookieForCurrentSession(mBiometricService.mCurrentAuthSession),
+                BiometricConstants.BIOMETRIC_ERROR_CANCELED,
+                ERROR_CANCELED);
+        waitForIdle();
+
+        assertEquals(BiometricService.STATE_SHOWING_DEVICE_CREDENTIAL,
+                mBiometricService.mCurrentAuthSession.mState);
+        verify(mReceiver1, never()).onError(anyInt(), anyString());
+    }
+
+    @Test
+    public void testLockout_whileAuthenticating_credentialAllowed() throws Exception {
+        setupAuthForOnly(BiometricAuthenticator.TYPE_FINGERPRINT);
+        invokeAuthenticateAndStart(mBiometricService.mImpl, mReceiver1,
+                false /* requireConfirmation */, true /* allowDeviceCredential */);
+
+        assertEquals(BiometricService.STATE_AUTH_STARTED,
+                mBiometricService.mCurrentAuthSession.mState);
+
+        mBiometricService.mInternalReceiver.onError(
+                getCookieForCurrentSession(mBiometricService.mCurrentAuthSession),
+                BiometricConstants.BIOMETRIC_ERROR_LOCKOUT,
+                ERROR_LOCKOUT);
+        waitForIdle();
+
+        assertEquals(BiometricService.STATE_SHOWING_DEVICE_CREDENTIAL,
+                mBiometricService.mCurrentAuthSession.mState);
+        verify(mBiometricService.mStatusBarService).onBiometricError(
+                eq(BiometricConstants.BIOMETRIC_ERROR_LOCKOUT),
+                eq(ERROR_LOCKOUT));
+    }
+
+    @Test
+    public void testLockout_whenAuthenticating_credentialNotAllowed() throws Exception {
+        setupAuthForOnly(BiometricAuthenticator.TYPE_FINGERPRINT);
+        invokeAuthenticateAndStart(mBiometricService.mImpl, mReceiver1,
+                false /* requireConfirmation */, false /* allowDeviceCredential */);
+
+        assertEquals(BiometricService.STATE_AUTH_STARTED,
+                mBiometricService.mCurrentAuthSession.mState);
+
+        mBiometricService.mInternalReceiver.onError(
+                getCookieForCurrentSession(mBiometricService.mCurrentAuthSession),
+                BiometricConstants.BIOMETRIC_ERROR_UNABLE_TO_PROCESS,
+                ERROR_UNABLE_TO_PROCESS);
+        waitForIdle();
+
+        assertEquals(BiometricService.STATE_ERROR_PENDING_SYSUI,
+                mBiometricService.mCurrentAuthSession.mState);
+        verify(mBiometricService.mStatusBarService).onBiometricError(
+                eq(BiometricConstants.BIOMETRIC_ERROR_UNABLE_TO_PROCESS),
+                eq(ERROR_UNABLE_TO_PROCESS));
+    }
+
+    @Test
     public void testDismissedReasonUserCancel_whileAuthenticating_cancelsHalAuthentication()
             throws Exception {
         setupAuthForOnly(BiometricAuthenticator.TYPE_FINGERPRINT);
         invokeAuthenticateAndStart(mBiometricService.mImpl, mReceiver1,
-                false /* requireConfirmation */);
+                false /* requireConfirmation */, false /* allowDeviceCredential */);
 
         mBiometricService.mInternalReceiver
                 .onDialogDismissed(BiometricPrompt.DISMISSED_REASON_USER_CANCEL);
@@ -575,7 +774,7 @@
     public void testDismissedReasonNegative_whilePaused_doesntInvokeHalCancel() throws Exception {
         setupAuthForOnly(BiometricAuthenticator.TYPE_FACE);
         invokeAuthenticateAndStart(mBiometricService.mImpl, mReceiver1,
-                false /* requireConfirmation */);
+                false /* requireConfirmation */, false /* allowDeviceCredential */);
 
         mBiometricService.mInternalReceiver.onError(
                 getCookieForCurrentSession(mBiometricService.mCurrentAuthSession),
@@ -598,7 +797,7 @@
     public void testDismissedReasonUserCancel_whilePaused_doesntInvokeHalCancel() throws Exception {
         setupAuthForOnly(BiometricAuthenticator.TYPE_FACE);
         invokeAuthenticateAndStart(mBiometricService.mImpl, mReceiver1,
-                false /* requireConfirmation */);
+                false /* requireConfirmation */, false /* allowDeviceCredential */);
 
         mBiometricService.mInternalReceiver.onError(
                 getCookieForCurrentSession(mBiometricService.mCurrentAuthSession),
@@ -621,7 +820,7 @@
     public void testDismissedReasonUserCancel_whenPendingConfirmation() throws Exception {
         setupAuthForOnly(BiometricAuthenticator.TYPE_FACE);
         invokeAuthenticateAndStart(mBiometricService.mImpl, mReceiver1,
-                true /* requireConfirmation */);
+                true /* requireConfirmation */, false /* allowDeviceCredential */);
 
         mBiometricService.mInternalReceiver.onAuthenticationSucceeded(
                 true /* requireConfirmation */,
@@ -648,7 +847,7 @@
     public void testAcquire_whenAuthenticating_sentToSystemUI() throws Exception {
         setupAuthForOnly(BiometricAuthenticator.TYPE_FINGERPRINT);
         invokeAuthenticateAndStart(mBiometricService.mImpl, mReceiver1,
-                false /* requireConfirmation */);
+                false /* requireConfirmation */, false /* allowDeviceCredential */);
 
         mBiometricService.mInternalReceiver.onAcquired(
                 FingerprintManager.FINGERPRINT_ACQUIRED_IMAGER_DIRTY,
@@ -698,9 +897,10 @@
     }
 
     private void invokeAuthenticateAndStart(IBiometricService.Stub service,
-            IBiometricServiceReceiver receiver, boolean requireConfirmation) throws Exception {
+            IBiometricServiceReceiver receiver, boolean requireConfirmation,
+            boolean allowDeviceCredential) throws Exception {
         // Request auth, creates a pending session
-        invokeAuthenticate(service, receiver, requireConfirmation);
+        invokeAuthenticate(service, receiver, requireConfirmation, allowDeviceCredential);
         waitForIdle();
 
         startPendingAuthSession(mBiometricService);
@@ -720,20 +920,25 @@
     }
 
     private static void invokeAuthenticate(IBiometricService.Stub service,
-            IBiometricServiceReceiver receiver, boolean requireConfirmation) throws Exception {
+            IBiometricServiceReceiver receiver, boolean requireConfirmation,
+            boolean allowDeviceCredential) throws Exception {
         service.authenticate(
                 new Binder() /* token */,
                 0 /* sessionId */,
                 0 /* userId */,
                 receiver,
                 TEST_PACKAGE_NAME /* packageName */,
-                createTestBiometricPromptBundle(requireConfirmation),
-                null /* IBiometricConfirmDeviceCredentialCallback */);
+                createTestBiometricPromptBundle(requireConfirmation, allowDeviceCredential));
     }
 
-    private static Bundle createTestBiometricPromptBundle(boolean requireConfirmation) {
+    private static Bundle createTestBiometricPromptBundle(boolean requireConfirmation,
+            boolean allowDeviceCredential) {
         final Bundle bundle = new Bundle();
         bundle.putBoolean(BiometricPrompt.KEY_REQUIRE_CONFIRMATION, requireConfirmation);
+
+        if (allowDeviceCredential) {
+            bundle.putBoolean(BiometricPrompt.KEY_ALLOW_DEVICE_CREDENTIAL, true);
+        }
         return bundle;
     }
 
@@ -742,6 +947,11 @@
         return session.mModalitiesMatched.values().iterator().next();
     }
 
+    private static int getCookieForPendingSession(BiometricService.AuthSession session) {
+        assertEquals(session.mModalitiesWaiting.values().size(), 1);
+        return session.mModalitiesWaiting.values().iterator().next();
+    }
+
     private static void waitForIdle() {
         InstrumentationRegistry.getInstrumentation().waitForIdleSync();
     }
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 a25e40f..9a1fd9c 100644
--- a/services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerTest.java
+++ b/services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerTest.java
@@ -2650,6 +2650,21 @@
         verifyStayOnWhilePluggedCleared(false);
     }
 
+    public void testIsActiveSupervisionApp() throws Exception {
+        when(mServiceContext.resources
+                .getString(R.string.config_defaultSupervisionProfileOwnerComponent))
+                .thenReturn(admin1.flattenToString());
+
+        final int PROFILE_USER = 15;
+        final int PROFILE_ADMIN = UserHandle.getUid(PROFILE_USER, 19436);
+        addManagedProfile(admin1, PROFILE_ADMIN, admin1);
+        mContext.binder.callingUid = PROFILE_ADMIN;
+
+        final DevicePolicyManagerInternal dpmi =
+                LocalServices.getService(DevicePolicyManagerInternal.class);
+        assertTrue(dpmi.isActiveSupervisionApp(PROFILE_ADMIN));
+    }
+
     // Test if lock timeout on managed profile is handled correctly depending on whether profile
     // uses separate challenge.
     public void testSetMaximumTimeToLockProfile() throws Exception {
diff --git a/services/tests/servicestests/src/com/android/server/display/whitebalance/AmbientLuxTest.java b/services/tests/servicestests/src/com/android/server/display/whitebalance/AmbientLuxTest.java
index 0d5a7d6..acf2d0e 100644
--- a/services/tests/servicestests/src/com/android/server/display/whitebalance/AmbientLuxTest.java
+++ b/services/tests/servicestests/src/com/android/server/display/whitebalance/AmbientLuxTest.java
@@ -78,6 +78,8 @@
     @Mock private TypedArray mBiases;
     @Mock private TypedArray mHighLightBrightnesses;
     @Mock private TypedArray mHighLightBiases;
+    @Mock private TypedArray mAmbientColorTemperatures;
+    @Mock private TypedArray mDisplayColorTemperatures;
 
     @Before
     public void setUp() throws Exception {
@@ -105,10 +107,10 @@
                 HIGH_LIGHT_AMBIENT_COLOR_TEMPERATURE);
         when(mResourcesSpy.obtainTypedArray(
                 R.array.config_displayWhiteBalanceAmbientColorTemperatures))
-                .thenReturn(createTypedArray());
+                .thenReturn(mAmbientColorTemperatures);
         when(mResourcesSpy.obtainTypedArray(
                 R.array.config_displayWhiteBalanceDisplayColorTemperatures))
-                .thenReturn(createTypedArray());
+                .thenReturn(mDisplayColorTemperatures);
 
         when(mResourcesSpy.obtainTypedArray(
                 R.array.config_displayWhiteBalanceLowLightAmbientBrightnesses))
@@ -388,6 +390,16 @@
         assertEquals(controller.mPendingAmbientColorTemperature, ambientColorTemperature, 0.001);
     }
 
+    @Test
+    public void testWhiteBalance_updateWithEmptyFilter() throws Exception {
+        setAmbientColorTemperatures(5300.0f, 6000.0f, 7000.0f, 8000.0f);
+        setDisplayColorTemperatures(6300.0f, 6400.0f, 6850.0f, 7450.0f);
+        DisplayWhiteBalanceController controller =
+                DisplayWhiteBalanceFactory.create(mHandler, mSensorManagerMock, mResourcesSpy);
+        controller.updateAmbientColorTemperature();
+        assertEquals(-1.0f, controller.mPendingAmbientColorTemperature, 0);
+    }
+
     void mockThrottler() {
         when(mResourcesSpy.getInteger(
                 R.integer.config_displayWhiteBalanceDecreaseDebounce)).thenReturn(0);
@@ -455,6 +467,14 @@
         setFloatArrayResource(mHighLightBiases, vals);
     }
 
+    private void setAmbientColorTemperatures(float... vals) {
+        setFloatArrayResource(mAmbientColorTemperatures, vals);
+    }
+
+    private void setDisplayColorTemperatures(float... vals) {
+        setFloatArrayResource(mDisplayColorTemperatures, vals);
+    }
+
     private void setFloatArrayResource(TypedArray array, float[] vals) {
         when(array.length()).thenReturn(vals.length);
         for (int i = 0; i < vals.length; i++) {
diff --git a/services/tests/servicestests/src/com/android/server/hdmi/ArcTerminationActionFromAvrTest.java b/services/tests/servicestests/src/com/android/server/hdmi/ArcTerminationActionFromAvrTest.java
index 11bd29d..ad3e040 100644
--- a/services/tests/servicestests/src/com/android/server/hdmi/ArcTerminationActionFromAvrTest.java
+++ b/services/tests/servicestests/src/com/android/server/hdmi/ArcTerminationActionFromAvrTest.java
@@ -28,6 +28,7 @@
 import androidx.test.filters.SmallTest;
 
 import org.junit.Before;
+import org.junit.Ignore;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import org.junit.runners.JUnit4;
@@ -114,6 +115,7 @@
     }
 
     @Test
+    @Ignore("b/120845532")
     public void testSendMessage_notSuccess() {
         mSendCecCommandSuccess = false;
         mShouldDispatchReportArcTerminated = false;
diff --git a/services/tests/servicestests/src/com/android/server/hdmi/HdmiCecLocalDeviceAudioSystemTest.java b/services/tests/servicestests/src/com/android/server/hdmi/HdmiCecLocalDeviceAudioSystemTest.java
index a89198a..0a1899b 100644
--- a/services/tests/servicestests/src/com/android/server/hdmi/HdmiCecLocalDeviceAudioSystemTest.java
+++ b/services/tests/servicestests/src/com/android/server/hdmi/HdmiCecLocalDeviceAudioSystemTest.java
@@ -232,6 +232,7 @@
     }
 
     @Test
+    @Ignore("b/120845532")
     public void handleGiveSystemAudioModeStatus_originalOff() throws Exception {
         HdmiCecMessage expectedMessage =
                 HdmiCecMessageBuilder.buildReportSystemAudioMode(
@@ -301,6 +302,7 @@
     }
 
     @Test
+    @Ignore("b/120845532")
     public void handleSetSystemAudioMode_setOn_orignalOff() throws Exception {
         mMusicMute = true;
         HdmiCecMessage messageSet =
@@ -328,6 +330,7 @@
     }
 
     @Test
+    @Ignore("b/120845532")
     public void handleSystemAudioModeRequest_turnOffByTv() throws Exception {
         assertThat(mMusicMute).isFalse();
         // Check if feature correctly turned off
@@ -497,6 +500,7 @@
     }
 
     @Test
+    @Ignore("b/120845532")
     public void handleRequestArcTerminate_arcIsNotOn() throws Exception {
         assertThat(mHdmiCecLocalDeviceAudioSystem.isArcEnabled()).isFalse();
         HdmiCecMessage message =
@@ -671,6 +675,7 @@
     }
 
     @Test
+    @Ignore("b/120845532")
     public void handleReportPhysicalAddress_differentPath_addDevice() {
         assertThat(mInvokeDeviceEventState).isNotEqualTo(DEVICE_EVENT_ADD_DEVICE);
         HdmiDeviceInfo oldDevice = new HdmiDeviceInfo(
diff --git a/services/tests/servicestests/src/com/android/server/hdmi/HdmiCecLocalDevicePlaybackTest.java b/services/tests/servicestests/src/com/android/server/hdmi/HdmiCecLocalDevicePlaybackTest.java
index b8799c3..0062a17 100644
--- a/services/tests/servicestests/src/com/android/server/hdmi/HdmiCecLocalDevicePlaybackTest.java
+++ b/services/tests/servicestests/src/com/android/server/hdmi/HdmiCecLocalDevicePlaybackTest.java
@@ -99,6 +99,7 @@
     }
 
     @Test
+    @Ignore("b/120845532")
     public void handleSetSystemAudioModeOn_audioSystemBroadcast() {
         mHdmiControlService.setSystemAudioActivated(false);
         assertThat(mHdmiCecLocalDevicePlayback.mService.isSystemAudioActivated()).isFalse();
@@ -110,6 +111,7 @@
     }
 
     @Test
+    @Ignore("b/120845532")
     public void handleSetSystemAudioModeOff_audioSystemToPlayback() {
         mHdmiCecLocalDevicePlayback.mService.setSystemAudioActivated(true);
         assertThat(mHdmiCecLocalDevicePlayback.mService.isSystemAudioActivated()).isTrue();
@@ -123,6 +125,7 @@
     }
 
     @Test
+    @Ignore("b/120845532")
     public void handleSystemAudioModeStatusOn_DirectltToLocalDeviceFromAudioSystem() {
         mHdmiControlService.setSystemAudioActivated(false);
         assertThat(mHdmiCecLocalDevicePlayback.mService.isSystemAudioActivated()).isFalse();
diff --git a/services/tests/servicestests/src/com/android/server/hdmi/HdmiControlServiceBinderAPITest.java b/services/tests/servicestests/src/com/android/server/hdmi/HdmiControlServiceBinderAPITest.java
new file mode 100644
index 0000000..c6cf9b1
--- /dev/null
+++ b/services/tests/servicestests/src/com/android/server/hdmi/HdmiControlServiceBinderAPITest.java
@@ -0,0 +1,212 @@
+/*
+ * 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.hdmi;
+
+import static android.os.SystemClock.sleep;
+import static com.android.server.hdmi.HdmiControlService.INITIATED_BY_ENABLE_CEC;
+import static com.google.common.truth.Truth.assertThat;
+import static junit.framework.Assert.assertEquals;
+
+import android.hardware.hdmi.HdmiControlManager;
+import android.hardware.hdmi.HdmiPortInfo;
+import android.hardware.hdmi.IHdmiControlCallback;
+import android.os.Looper;
+import android.os.SystemProperties;
+import android.os.test.TestLooper;
+import android.util.Slog;
+
+import androidx.test.InstrumentationRegistry;
+import androidx.test.filters.SmallTest;
+
+import java.util.ArrayList;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.JUnit4;
+
+/**
+ * Tests for {@link HdmiControlServiceBinderAPITest} class.
+ */
+@SmallTest
+@RunWith(JUnit4.class)
+public class HdmiControlServiceBinderAPITest {
+
+    private class HdmiCecLocalDeviceMyDevice extends HdmiCecLocalDevice {
+
+        private boolean mCanGoToStandby;
+        private boolean mIsStandby;
+        private boolean mIsDisabled;
+
+        protected HdmiCecLocalDeviceMyDevice(HdmiControlService service, int deviceType) {
+            super(service, deviceType);
+        }
+
+        @Override
+        protected void onAddressAllocated(int logicalAddress, int reason) {
+        }
+
+        @Override
+        protected int getPreferredAddress() {
+            return 0;
+        }
+
+        @Override
+        protected void setPreferredAddress(int addr) {
+        }
+
+        @Override
+        protected boolean canGoToStandby() {
+            return mCanGoToStandby;
+        }
+
+        @Override
+        protected void disableDevice(
+            boolean initiatedByCec, final PendingActionClearedCallback originalCallback) {
+            mIsDisabled = true;
+            originalCallback.onCleared(this);
+        }
+
+        @Override
+        protected void onStandby(boolean initiatedByCec, int standbyAction) {
+            mIsStandby = true;
+        }
+
+        protected boolean isStandby() {
+            return mIsStandby;
+        }
+
+        protected boolean isDisabled() {
+            return mIsDisabled;
+        }
+
+        protected void setCanGoToStandby(boolean canGoToStandby) {
+            mCanGoToStandby = canGoToStandby;
+        }
+    }
+
+    private static final String TAG = "HdmiControlServiceBinderAPITest";
+    private HdmiControlService mHdmiControlService;
+    private HdmiCecController mHdmiCecController;
+    private HdmiCecLocalDevicePlayback mPlaybackDevice;
+    private FakeNativeWrapper mNativeWrapper;
+    private Looper mMyLooper;
+    private TestLooper mTestLooper = new TestLooper();
+    private ArrayList<HdmiCecLocalDevice> mLocalDevices = new ArrayList<>();
+    private HdmiPortInfo[] mHdmiPortInfo;
+    private int mResult;
+    private int mPowerStatus;
+
+    @Before
+    public void SetUp() {
+        mHdmiControlService =
+            new HdmiControlService(InstrumentationRegistry.getTargetContext()) {
+                @Override
+                void sendCecCommand(HdmiCecMessage command) {
+                    switch (command.getOpcode()) {
+                        case Constants.MESSAGE_GIVE_DEVICE_POWER_STATUS:
+                            HdmiCecMessage message =
+                                HdmiCecMessageBuilder.buildReportPowerStatus(
+                                    Constants.ADDR_TV,
+                                    Constants.ADDR_PLAYBACK_1,
+                                    HdmiControlManager.POWER_STATUS_ON);
+                            handleCecCommand(message);
+                            break;
+                        default:
+                            return;
+                    }
+                }
+
+                @Override
+                boolean isPowerStandby() {
+                    return mPowerStatus == HdmiControlManager.POWER_STATUS_STANDBY;
+                }
+            };
+        mMyLooper = mTestLooper.getLooper();
+
+        mPlaybackDevice = new HdmiCecLocalDevicePlayback(mHdmiControlService) {
+            @Override
+            void setIsActiveSource(boolean on) {
+                mIsActiveSource = on;
+            }
+
+            @Override
+            protected void wakeUpIfActiveSource() {}
+
+            @Override
+            protected void setPreferredAddress(int addr) {}
+
+            @Override
+            protected int getPreferredAddress() {
+                return Constants.ADDR_PLAYBACK_1;
+            }
+        };
+        mPlaybackDevice.init();
+
+        mHdmiControlService.setIoLooper(mMyLooper);
+
+        mNativeWrapper = new FakeNativeWrapper();
+        mHdmiCecController =
+            HdmiCecController.createWithNativeWrapper(mHdmiControlService, mNativeWrapper);
+        mHdmiControlService.setCecController(mHdmiCecController);
+        mHdmiControlService.setHdmiMhlController(HdmiMhlControllerStub.create(mHdmiControlService));
+        mHdmiControlService.setMessageValidator(new HdmiCecMessageValidator(mHdmiControlService));
+
+        mLocalDevices.add(mPlaybackDevice);
+        mHdmiPortInfo = new HdmiPortInfo[1];
+        mHdmiPortInfo[0] =
+            new HdmiPortInfo(1, HdmiPortInfo.PORT_INPUT, 0x2100, true, false, false);
+        mNativeWrapper.setPortInfo(mHdmiPortInfo);
+        mHdmiControlService.initPortInfo();
+        mResult = -1;
+        mPowerStatus = HdmiControlManager.POWER_STATUS_ON;
+
+        mTestLooper.dispatchAll();
+    }
+
+    @Test
+    public void oneTouchPlay_addressNotAllocated() {
+        assertThat(mHdmiControlService.isAddressAllocated()).isFalse();
+        mHdmiControlService.oneTouchPlay(new IHdmiControlCallback.Stub() {
+            @Override
+            public void onComplete(int result) {
+                mResult = result;
+            }
+        });
+        assertEquals(mResult, -1);
+        assertThat(mPlaybackDevice.mIsActiveSource).isFalse();
+
+        mHdmiControlService.allocateLogicalAddress(mLocalDevices, INITIATED_BY_ENABLE_CEC);
+        mTestLooper.dispatchAll();
+        assertThat(mHdmiControlService.isAddressAllocated()).isTrue();
+        assertEquals(mResult, HdmiControlManager.RESULT_SUCCESS);
+        assertThat(mPlaybackDevice.mIsActiveSource).isTrue();
+    }
+
+    @Test
+    public void oneTouchPlay_addressAllocated() {
+        mHdmiControlService.allocateLogicalAddress(mLocalDevices, INITIATED_BY_ENABLE_CEC);
+        mTestLooper.dispatchAll();
+        assertThat(mHdmiControlService.isAddressAllocated()).isTrue();
+        mHdmiControlService.oneTouchPlay(new IHdmiControlCallback.Stub() {
+            @Override
+            public void onComplete(int result) {
+                mResult = result;
+            }
+        });
+        assertEquals(mResult, HdmiControlManager.RESULT_SUCCESS);
+        assertThat(mPlaybackDevice.mIsActiveSource).isTrue();
+    }
+}
diff --git a/services/tests/servicestests/src/com/android/server/hdmi/SystemAudioInitiationActionFromAvrTest.java b/services/tests/servicestests/src/com/android/server/hdmi/SystemAudioInitiationActionFromAvrTest.java
index 440a49a..6dcff35 100644
--- a/services/tests/servicestests/src/com/android/server/hdmi/SystemAudioInitiationActionFromAvrTest.java
+++ b/services/tests/servicestests/src/com/android/server/hdmi/SystemAudioInitiationActionFromAvrTest.java
@@ -221,6 +221,7 @@
     }
 
     @Test
+    @Ignore("b/120845532")
     public void testTvSupport() {
         resetTestVariables();
         mShouldDispatchActiveSource = true;
diff --git a/services/tests/servicestests/src/com/android/server/integrity/engine/RuleEvaluatorTest.java b/services/tests/servicestests/src/com/android/server/integrity/engine/RuleEvaluatorTest.java
new file mode 100644
index 0000000..1fcd0ef
--- /dev/null
+++ b/services/tests/servicestests/src/com/android/server/integrity/engine/RuleEvaluatorTest.java
@@ -0,0 +1,130 @@
+/*
+ * 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.integrity.engine;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotEquals;
+
+import com.android.server.integrity.model.AppInstallMetadata;
+import com.android.server.integrity.model.AtomicFormula;
+import com.android.server.integrity.model.OpenFormula;
+import com.android.server.integrity.model.Rule;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.JUnit4;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.List;
+
+@RunWith(JUnit4.class)
+public class RuleEvaluatorTest {
+
+    private static final String PACKAGE_NAME_1 = "com.test.app";
+    private static final String PACKAGE_NAME_2 = "com.test.app2";
+    private static final String APP_CERTIFICATE = "test_cert";
+    private static final AppInstallMetadata APP_INSTALL_METADATA =
+            new AppInstallMetadata.Builder()
+                    .setPackageName(PACKAGE_NAME_1)
+                    .setAppCertificate(APP_CERTIFICATE)
+                    .build();
+
+    @Test
+    public void testMatchRules_emptyRules() {
+        List<Rule> rules = new ArrayList<>();
+
+        Rule matchedRule = RuleEvaluator.evaluateRules(rules, APP_INSTALL_METADATA);
+
+        assertEquals(Rule.EMPTY, matchedRule);
+    }
+
+    @Test
+    public void testMatchRules_emptyMatch() {
+        Rule rule1 = new Rule(
+                new AtomicFormula(AtomicFormula.Key.PACKAGE_NAME, AtomicFormula.Operator.EQ,
+                        PACKAGE_NAME_2), Rule.Effect.DENY);
+
+        Rule matchedRule = RuleEvaluator.evaluateRules(Collections.singletonList(rule1),
+                APP_INSTALL_METADATA);
+
+        assertEquals(Rule.EMPTY, matchedRule);
+    }
+
+
+    @Test
+    public void testMatchRules_oneMatch() {
+        Rule rule1 = new Rule(
+                new AtomicFormula(AtomicFormula.Key.PACKAGE_NAME, AtomicFormula.Operator.EQ,
+                        PACKAGE_NAME_1), Rule.Effect.DENY);
+        Rule rule2 = new Rule(
+                new AtomicFormula(AtomicFormula.Key.PACKAGE_NAME, AtomicFormula.Operator.EQ,
+                        PACKAGE_NAME_2), Rule.Effect.DENY);
+
+        Rule matchedRule = RuleEvaluator.evaluateRules(Arrays.asList(rule1, rule2),
+                APP_INSTALL_METADATA);
+
+        assertEquals(rule1, matchedRule);
+    }
+
+    @Test
+    public void testMatchRules_multipleMatches() {
+        Rule rule1 = new Rule(
+                new AtomicFormula(AtomicFormula.Key.PACKAGE_NAME, AtomicFormula.Operator.EQ,
+                        PACKAGE_NAME_1), Rule.Effect.DENY);
+        OpenFormula openFormula2 = new OpenFormula(OpenFormula.Connector.AND, Arrays.asList(
+                new AtomicFormula(AtomicFormula.Key.PACKAGE_NAME, AtomicFormula.Operator.EQ,
+                        PACKAGE_NAME_1),
+                new AtomicFormula(AtomicFormula.Key.APP_CERTIFICATE,
+                        AtomicFormula.Operator.EQ,
+                        APP_CERTIFICATE)));
+        Rule rule2 = new Rule(
+                openFormula2, Rule.Effect.DENY);
+
+        Rule matchedRule = RuleEvaluator.evaluateRules(Arrays.asList(rule1, rule2),
+                APP_INSTALL_METADATA);
+
+        assertNotEquals(Rule.EMPTY, matchedRule);
+    }
+
+    @Test
+    public void testMatchRules_ruleWithNot() {
+        OpenFormula openFormula = new OpenFormula(OpenFormula.Connector.NOT,
+                Collections.singletonList(
+                        new AtomicFormula(AtomicFormula.Key.PACKAGE_NAME, AtomicFormula.Operator.EQ,
+                                PACKAGE_NAME_2)));
+        Rule rule = new Rule(openFormula, Rule.Effect.DENY);
+
+        Rule matchedRule = RuleEvaluator.evaluateRules(Collections.singletonList(rule),
+                APP_INSTALL_METADATA);
+
+        assertEquals(rule, matchedRule);
+    }
+
+    @Test
+    public void testMatchRules_ruleWithIntegerOperators() {
+        Rule rule1 = new Rule(
+                new AtomicFormula(AtomicFormula.Key.VERSION_CODE, AtomicFormula.Operator.GT,
+                        1), Rule.Effect.DENY);
+
+        Rule matchedRule = RuleEvaluator.evaluateRules(Collections.singletonList(rule1),
+                APP_INSTALL_METADATA);
+
+        assertEquals(rule1, matchedRule);
+    }
+}
diff --git a/services/tests/servicestests/src/com/android/server/integrity/model/AtomicFormulaTest.java b/services/tests/servicestests/src/com/android/server/integrity/model/AtomicFormulaTest.java
new file mode 100644
index 0000000..1cb2fb3
--- /dev/null
+++ b/services/tests/servicestests/src/com/android/server/integrity/model/AtomicFormulaTest.java
@@ -0,0 +1,100 @@
+/*
+ * 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.integrity.model;
+
+import static com.android.server.testutils.TestUtils.assertExpectException;
+
+import static org.junit.Assert.assertEquals;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.JUnit4;
+
+@RunWith(JUnit4.class)
+public class AtomicFormulaTest {
+
+    @Test
+    public void testValidAtomicFormula_stringValue() {
+        AtomicFormula atomicFormula = new AtomicFormula(AtomicFormula.Key.PACKAGE_NAME,
+                AtomicFormula.Operator.EQ, "com.test.app");
+
+        assertEquals(AtomicFormula.Key.PACKAGE_NAME, atomicFormula.getKey());
+        assertEquals(AtomicFormula.Operator.EQ, atomicFormula.getOperator());
+        assertEquals("com.test.app", atomicFormula.getStringValue());
+    }
+
+    @Test
+    public void testValidAtomicFormula_intValue() {
+        AtomicFormula atomicFormula = new AtomicFormula(AtomicFormula.Key.VERSION_CODE,
+                AtomicFormula.Operator.LE, 1);
+
+        assertEquals(AtomicFormula.Key.VERSION_CODE, atomicFormula.getKey());
+        assertEquals(AtomicFormula.Operator.LE, atomicFormula.getOperator());
+        assertEquals(1, atomicFormula.getIntValue().intValue());
+    }
+
+    @Test
+    public void testValidAtomicFormula_boolValue() {
+        AtomicFormula atomicFormula = new AtomicFormula(AtomicFormula.Key.PRE_INSTALLED,
+                AtomicFormula.Operator.EQ, true);
+
+        assertEquals(AtomicFormula.Key.PRE_INSTALLED, atomicFormula.getKey());
+        assertEquals(AtomicFormula.Operator.EQ, atomicFormula.getOperator());
+        assertEquals(true, atomicFormula.getBoolValue());
+    }
+
+    @Test
+    public void testInvalidAtomicFormula_stringValue() {
+        assertExpectException(
+                IllegalArgumentException.class,
+                /* expectedExceptionMessageRegex */
+                String.format("Key %s cannot have string value", AtomicFormula.Key.VERSION_CODE),
+                () -> new AtomicFormula(AtomicFormula.Key.VERSION_CODE, AtomicFormula.Operator.EQ,
+                        "test-value"));
+    }
+
+    @Test
+    public void testInvalidAtomicFormula_intValue() {
+        assertExpectException(
+                IllegalArgumentException.class,
+                /* expectedExceptionMessageRegex */
+                String.format("Key %s cannot have integer value", AtomicFormula.Key.PACKAGE_NAME),
+                () -> new AtomicFormula(AtomicFormula.Key.PACKAGE_NAME, AtomicFormula.Operator.EQ,
+                        1));
+    }
+
+    @Test
+    public void testInvalidAtomicFormula_boolValue() {
+        assertExpectException(
+                IllegalArgumentException.class,
+                /* expectedExceptionMessageRegex */
+                String.format("Key %s cannot have boolean value", AtomicFormula.Key.PACKAGE_NAME),
+                () -> new AtomicFormula(AtomicFormula.Key.PACKAGE_NAME, AtomicFormula.Operator.EQ,
+                        true));
+    }
+
+    @Test
+    public void testValidateOperator_invalidKeyOperatorPair() {
+        assertExpectException(
+                IllegalArgumentException.class,
+                /* expectedExceptionMessageRegex */
+                String.format("Invalid operator %s used for key %s",
+                        AtomicFormula.Operator.LE, AtomicFormula.Key.PACKAGE_NAME),
+                () -> new AtomicFormula(AtomicFormula.Key.PACKAGE_NAME, AtomicFormula.Operator.LE,
+                        "test-value"));
+    }
+}
diff --git a/services/tests/servicestests/src/com/android/server/integrity/model/OpenFormulaTest.java b/services/tests/servicestests/src/com/android/server/integrity/model/OpenFormulaTest.java
new file mode 100644
index 0000000..2133a7d
--- /dev/null
+++ b/services/tests/servicestests/src/com/android/server/integrity/model/OpenFormulaTest.java
@@ -0,0 +1,67 @@
+/*
+ * 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.integrity.model;
+
+import static com.android.server.testutils.TestUtils.assertExpectException;
+
+import static org.junit.Assert.assertEquals;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.JUnit4;
+
+import java.util.Arrays;
+import java.util.Collections;
+
+@RunWith(JUnit4.class)
+public class OpenFormulaTest {
+
+    private static final AtomicFormula ATOMIC_FORMULA_1 = new AtomicFormula(
+            AtomicFormula.Key.PACKAGE_NAME, AtomicFormula.Operator.EQ, "test1");
+    private static final AtomicFormula ATOMIC_FORMULA_2 = new AtomicFormula(
+            AtomicFormula.Key.VERSION_CODE, AtomicFormula.Operator.EQ, 1);
+
+    @Test
+    public void testValidOpenFormula() {
+        OpenFormula openFormula = new OpenFormula(OpenFormula.Connector.AND,
+                Arrays.asList(ATOMIC_FORMULA_1, ATOMIC_FORMULA_2));
+
+        assertEquals(OpenFormula.Connector.AND, openFormula.getConnector());
+        assertEquals(Arrays.asList(ATOMIC_FORMULA_1, ATOMIC_FORMULA_2), openFormula.getFormulas());
+    }
+
+    @Test
+    public void testValidateAuxiliaryFormula_binaryConnectors() {
+        assertExpectException(
+                IllegalArgumentException.class,
+                /* expectedExceptionMessageRegex */
+                String.format("Connector %s must have at least 2 formulas",
+                        OpenFormula.Connector.AND),
+                () -> new OpenFormula(OpenFormula.Connector.AND,
+                        Collections.singletonList(ATOMIC_FORMULA_1)));
+    }
+
+    @Test
+    public void testValidateAuxiliaryFormula_unaryConnectors() {
+        assertExpectException(
+                IllegalArgumentException.class,
+                /* expectedExceptionMessageRegex */
+                String.format("Connector %s must have 1 formula only", OpenFormula.Connector.NOT),
+                () -> new OpenFormula(OpenFormula.Connector.NOT,
+                        Arrays.asList(ATOMIC_FORMULA_1, ATOMIC_FORMULA_2)));
+    }
+}
diff --git a/services/tests/servicestests/src/com/android/server/integrity/model/RuleTest.java b/services/tests/servicestests/src/com/android/server/integrity/model/RuleTest.java
new file mode 100644
index 0000000..048ee70
--- /dev/null
+++ b/services/tests/servicestests/src/com/android/server/integrity/model/RuleTest.java
@@ -0,0 +1,103 @@
+/*
+ * 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.integrity.model;
+
+import static com.android.server.testutils.TestUtils.assertExpectException;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotEquals;
+import static org.junit.Assert.assertNull;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.JUnit4;
+
+import java.util.Arrays;
+
+@RunWith(JUnit4.class)
+public class RuleTest {
+
+    private static final Rule.Effect DENY_EFFECT = Rule.Effect.DENY;
+    private static final String PACKAGE_NAME = "com.test.app";
+    private static final String APP_CERTIFICATE = "test_cert";
+    private static final Formula PACKAGE_NAME_ATOMIC_FORMULA =
+            new AtomicFormula(AtomicFormula.Key.PACKAGE_NAME, AtomicFormula.Operator.EQ,
+                    PACKAGE_NAME);
+    private static final Formula APP_CERTIFICATE_ATOMIC_FORMULA =
+            new AtomicFormula(AtomicFormula.Key.APP_CERTIFICATE, AtomicFormula.Operator.EQ,
+                    APP_CERTIFICATE);
+
+    @Test
+    public void testEmptyRule() {
+        Rule emptyRule = Rule.EMPTY;
+
+        assertNull(emptyRule.getFormula());
+        assertNull(emptyRule.getEffect());
+    }
+
+    @Test
+    public void testValidRule() {
+        Rule validRule = new Rule(PACKAGE_NAME_ATOMIC_FORMULA, DENY_EFFECT);
+
+        assertEquals(PACKAGE_NAME_ATOMIC_FORMULA, validRule.getFormula());
+        assertEquals(DENY_EFFECT, validRule.getEffect());
+    }
+
+    @Test
+    public void testInvalidRule_invalidEffect() {
+        assertExpectException(
+                NullPointerException.class,
+                /* expectedExceptionMessageRegex */ null,
+                () -> new Rule(PACKAGE_NAME_ATOMIC_FORMULA, null));
+    }
+
+    @Test
+    public void testInvalidRule_invalidFormula() {
+        assertExpectException(
+                NullPointerException.class,
+                /* expectedExceptionMessageRegex */ null,
+                () -> new Rule(null, DENY_EFFECT));
+    }
+
+    @Test
+    public void testToString() {
+        OpenFormula openFormula = new OpenFormula(OpenFormula.Connector.AND,
+                Arrays.asList(PACKAGE_NAME_ATOMIC_FORMULA, APP_CERTIFICATE_ATOMIC_FORMULA));
+        Rule rule = new Rule(openFormula, Rule.Effect.DENY);
+
+        String toString = rule.toString();
+
+        assertEquals(String.format("Rule: PACKAGE_NAME EQ %s AND APP_CERTIFICATE EQ %s, DENY",
+                PACKAGE_NAME, APP_CERTIFICATE), toString);
+    }
+
+    @Test
+    public void testEquals_trueCase() {
+        Rule rule1 = new Rule(PACKAGE_NAME_ATOMIC_FORMULA, DENY_EFFECT);
+        Rule rule2 = new Rule(PACKAGE_NAME_ATOMIC_FORMULA, DENY_EFFECT);
+
+        assertEquals(rule1, rule2);
+    }
+
+    @Test
+    public void testEquals_falseCase() {
+        Rule rule1 = new Rule(PACKAGE_NAME_ATOMIC_FORMULA, DENY_EFFECT);
+        Rule rule2 = new Rule(APP_CERTIFICATE_ATOMIC_FORMULA, DENY_EFFECT);
+
+        assertNotEquals(rule1, rule2);
+    }
+}
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 7cece1f..f9ac022 100644
--- a/services/tests/servicestests/src/com/android/server/locksettings/BaseLockSettingsServiceTests.java
+++ b/services/tests/servicestests/src/com/android/server/locksettings/BaseLockSettingsServiceTests.java
@@ -32,8 +32,11 @@
 import android.app.admin.DeviceStateCache;
 import android.app.trust.TrustManager;
 import android.content.ComponentName;
+import android.content.pm.PackageManager;
 import android.content.pm.UserInfo;
 import android.hardware.authsecret.V1_0.IAuthSecret;
+import android.hardware.face.FaceManager;
+import android.hardware.fingerprint.FingerprintManager;
 import android.os.FileUtils;
 import android.os.IProgressListener;
 import android.os.RemoteException;
@@ -95,6 +98,9 @@
     RecoverableKeyStoreManager mRecoverableKeyStoreManager;
     UserManagerInternal mUserManagerInternal;
     DeviceStateCache mDeviceStateCache;
+    FingerprintManager mFingerprintManager;
+    FaceManager mFaceManager;
+    PackageManager mPackageManager;
     protected boolean mHasSecureLockScreen;
 
     @Override
@@ -114,6 +120,9 @@
         mRecoverableKeyStoreManager = mock(RecoverableKeyStoreManager.class);
         mUserManagerInternal = mock(UserManagerInternal.class);
         mDeviceStateCache = mock(DeviceStateCache.class);
+        mFingerprintManager = mock(FingerprintManager.class);
+        mFaceManager = mock(FaceManager.class);
+        mPackageManager = mock(PackageManager.class);
 
         LocalServices.removeServiceForTest(LockSettingsInternal.class);
         LocalServices.removeServiceForTest(DevicePolicyManagerInternal.class);
@@ -123,7 +132,7 @@
 
         mContext = new MockLockSettingsContext(getContext(), mUserManager, mNotificationManager,
                 mDevicePolicyManager, mock(StorageManager.class), mock(TrustManager.class),
-                mock(KeyguardManager.class));
+                mock(KeyguardManager.class), mFingerprintManager, mFaceManager, mPackageManager);
         mStorage = new LockSettingsStorageTestable(mContext,
                 new File(getContext().getFilesDir(), "locksettings"));
         File storageDir = mStorage.mStorageDir;
@@ -181,6 +190,8 @@
                 new ComponentName("com.dummy.package", ".FakeDeviceOwner"));
         when(mUserManagerInternal.isDeviceManaged()).thenReturn(true);
         when(mDeviceStateCache.isDeviceProvisioned()).thenReturn(true);
+        mockBiometricsHardwareFingerprintsAndTemplates(PRIMARY_USER_ID);
+        mockBiometricsHardwareFingerprintsAndTemplates(MANAGED_PROFILE_USER_ID);
 
         mLocalService = LocalServices.getService(LockSettingsInternal.class);
     }
@@ -233,6 +244,18 @@
         return sm;
     }
 
+    private void mockBiometricsHardwareFingerprintsAndTemplates(int userId) {
+        // Hardware must be detected and fingerprints must be enrolled
+        when(mPackageManager.hasSystemFeature(PackageManager.FEATURE_FINGERPRINT)).thenReturn(true);
+        when(mFingerprintManager.isHardwareDetected()).thenReturn(true);
+        when(mFingerprintManager.hasEnrolledFingerprints(userId)).thenReturn(true);
+
+        // 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);
+    }
+
     @Override
     protected void tearDown() throws Exception {
         super.tearDown();
diff --git a/services/tests/servicestests/src/com/android/server/locksettings/LockSettingsServiceTestable.java b/services/tests/servicestests/src/com/android/server/locksettings/LockSettingsServiceTestable.java
index 65d6f45..fcd98e0 100644
--- a/services/tests/servicestests/src/com/android/server/locksettings/LockSettingsServiceTestable.java
+++ b/services/tests/servicestests/src/com/android/server/locksettings/LockSettingsServiceTestable.java
@@ -23,7 +23,6 @@
 import android.content.Context;
 import android.hardware.authsecret.V1_0.IAuthSecret;
 import android.os.Handler;
-import android.os.Looper;
 import android.os.Process;
 import android.os.RemoteException;
 import android.os.UserManagerInternal;
@@ -32,6 +31,7 @@
 import android.security.keystore.KeyPermanentlyInvalidatedException;
 
 import com.android.internal.widget.LockPatternUtils;
+import com.android.server.ServiceThread;
 import com.android.server.locksettings.recoverablekeystore.RecoverableKeyStoreManager;
 
 import java.io.FileNotFoundException;
@@ -70,8 +70,8 @@
         }
 
         @Override
-        public Handler getHandler() {
-            return new Handler(Looper.getMainLooper());
+        public Handler getHandler(ServiceThread handlerThread) {
+            return new Handler(handlerThread.getLooper());
         }
 
         @Override
diff --git a/services/tests/servicestests/src/com/android/server/locksettings/LockSettingsServiceTests.java b/services/tests/servicestests/src/com/android/server/locksettings/LockSettingsServiceTests.java
index 7354ad4..5818133 100644
--- a/services/tests/servicestests/src/com/android/server/locksettings/LockSettingsServiceTests.java
+++ b/services/tests/servicestests/src/com/android/server/locksettings/LockSettingsServiceTests.java
@@ -330,6 +330,27 @@
                 .lockScreenSecretChanged(CREDENTIAL_TYPE_NONE, null, MANAGED_PROFILE_USER_ID);
     }
 
+    public void testSetLockCredential_nullCredential_removeBiometrics() throws RemoteException {
+        final String oldCredential = "oldPassword";
+
+        initializeStorageWithCredential(
+                PRIMARY_USER_ID,
+                oldCredential,
+                CREDENTIAL_TYPE_PATTERN,
+                PASSWORD_QUALITY_SOMETHING);
+        mService.setSeparateProfileChallengeEnabled(MANAGED_PROFILE_USER_ID, false, null);
+
+        mService.setLockCredential(null, CREDENTIAL_TYPE_NONE, oldCredential.getBytes(),
+                PASSWORD_QUALITY_UNSPECIFIED, PRIMARY_USER_ID, false);
+
+        // Verify fingerprint is removed
+        verify(mFingerprintManager).remove(any(), eq(PRIMARY_USER_ID), any());
+        verify(mFaceManager).remove(any(), eq(PRIMARY_USER_ID), any());
+
+        verify(mFingerprintManager).remove(any(), eq(MANAGED_PROFILE_USER_ID), any());
+        verify(mFaceManager).remove(any(), eq(MANAGED_PROFILE_USER_ID), any());
+    }
+
     public void testSetLockCredential_forUnifiedToSeparateChallengeProfile_sendsNewCredentials()
             throws Exception {
         final String parentPassword = "parentPassword";
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 8e0d7be..2a169b7 100644
--- a/services/tests/servicestests/src/com/android/server/locksettings/LockSettingsStorageTests.java
+++ b/services/tests/servicestests/src/com/android/server/locksettings/LockSettingsStorageTests.java
@@ -24,8 +24,11 @@
 import android.app.NotificationManager;
 import android.app.admin.DevicePolicyManager;
 import android.app.trust.TrustManager;
+import android.content.pm.PackageManager;
 import android.content.pm.UserInfo;
 import android.database.sqlite.SQLiteDatabase;
+import android.hardware.face.FaceManager;
+import android.hardware.fingerprint.FingerprintManager;
 import android.os.FileUtils;
 import android.os.SystemClock;
 import android.os.UserManager;
@@ -86,7 +89,9 @@
 
         MockLockSettingsContext context = new MockLockSettingsContext(getContext(), mockUserManager,
                 mock(NotificationManager.class), mock(DevicePolicyManager.class),
-                mock(StorageManager.class), mock(TrustManager.class), mock(KeyguardManager.class));
+                mock(StorageManager.class), mock(TrustManager.class), mock(KeyguardManager.class),
+                mock(FingerprintManager.class), mock(FaceManager.class),
+                mock(PackageManager.class));
         mStorage = new LockSettingsStorageTestable(context,
                 new File(getContext().getFilesDir(), "locksettings"));
         mStorage.setDatabaseOnCreateCallback(new LockSettingsStorage.Callback() {
diff --git a/services/tests/servicestests/src/com/android/server/locksettings/MockLockSettingsContext.java b/services/tests/servicestests/src/com/android/server/locksettings/MockLockSettingsContext.java
index b332532..2b9a05c 100644
--- a/services/tests/servicestests/src/com/android/server/locksettings/MockLockSettingsContext.java
+++ b/services/tests/servicestests/src/com/android/server/locksettings/MockLockSettingsContext.java
@@ -23,6 +23,8 @@
 import android.content.Context;
 import android.content.ContextWrapper;
 import android.content.pm.PackageManager;
+import android.hardware.face.FaceManager;
+import android.hardware.fingerprint.FingerprintManager;
 import android.os.UserManager;
 import android.os.storage.StorageManager;
 
@@ -34,11 +36,15 @@
     private StorageManager mStorageManager;
     private TrustManager mTrustManager;
     private KeyguardManager mKeyguardManager;
+    private FingerprintManager mFingerprintManager;
+    private FaceManager mFaceManager;
+    private PackageManager mPackageManager;
 
     public MockLockSettingsContext(Context base, UserManager userManager,
             NotificationManager notificationManager, DevicePolicyManager devicePolicyManager,
             StorageManager storageManager, TrustManager trustManager,
-            KeyguardManager keyguardManager) {
+            KeyguardManager keyguardManager, FingerprintManager fingerprintManager,
+            FaceManager faceManager, PackageManager packageManager) {
         super(base);
         mUserManager = userManager;
         mNotificationManager = notificationManager;
@@ -46,6 +52,9 @@
         mStorageManager = storageManager;
         mTrustManager = trustManager;
         mKeyguardManager = keyguardManager;
+        mFingerprintManager = fingerprintManager;
+        mFaceManager = faceManager;
+        mPackageManager = packageManager;
     }
 
     @Override
@@ -62,12 +71,21 @@
             return mTrustManager;
         } else if (KEYGUARD_SERVICE.equals(name)) {
             return mKeyguardManager;
+        } else if (FINGERPRINT_SERVICE.equals(name)) {
+            return mFingerprintManager;
+        } else if (FACE_SERVICE.equals(name)) {
+            return mFaceManager;
         } else {
             throw new RuntimeException("System service not mocked: " + name);
         }
     }
 
     @Override
+    public PackageManager getPackageManager() {
+        return mPackageManager;
+    }
+
+    @Override
     public void enforceCallingOrSelfPermission(String permission, String message) {
         // Skip permission checks for unit tests.
     }
diff --git a/services/tests/servicestests/src/com/android/server/pm/UserManagerServiceUserInfoTest.java b/services/tests/servicestests/src/com/android/server/pm/UserManagerServiceUserInfoTest.java
index 806c71a..6d5b994 100644
--- a/services/tests/servicestests/src/com/android/server/pm/UserManagerServiceUserInfoTest.java
+++ b/services/tests/servicestests/src/com/android/server/pm/UserManagerServiceUserInfoTest.java
@@ -132,6 +132,7 @@
         user.profileBadge = 2;
         user.partial = true;
         user.guestToRemove = true;
+        user.preCreated = true;
         return user;
     }
 
@@ -147,5 +148,6 @@
         assertEquals("profile badge not preseved", one.profileBadge, two.profileBadge);
         assertEquals("partial not preseved", one.partial, two.partial);
         assertEquals("guestToRemove not preseved", one.guestToRemove, two.guestToRemove);
+        assertEquals("preCreated not preseved", one.preCreated, two.preCreated);
     }
 }
diff --git a/services/tests/servicestests/src/com/android/server/rollback/RollbackStoreTest.java b/services/tests/servicestests/src/com/android/server/rollback/RollbackStoreTest.java
new file mode 100644
index 0000000..ee3b15a
--- /dev/null
+++ b/services/tests/servicestests/src/com/android/server/rollback/RollbackStoreTest.java
@@ -0,0 +1,318 @@
+/*
+ * 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.rollback;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import android.content.pm.VersionedPackage;
+import android.content.rollback.PackageRollbackInfo;
+import android.util.IntArray;
+import android.util.SparseLongArray;
+
+import com.google.common.truth.Correspondence;
+
+import org.json.JSONObject;
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.rules.TemporaryFolder;
+import org.junit.runner.RunWith;
+import org.junit.runners.JUnit4;
+
+import java.io.File;
+import java.time.Instant;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Objects;
+
+@RunWith(JUnit4.class)
+public class RollbackStoreTest {
+
+    private static final int ID = 123;
+
+    private static final Correspondence<VersionedPackage, VersionedPackage> VER_PKG_CORR =
+            new Correspondence<VersionedPackage, VersionedPackage>() {
+                @Override
+                public boolean compare(VersionedPackage a, VersionedPackage b) {
+                    if (a == null || b == null) {
+                        return a == b;
+                    }
+                    return a.getLongVersionCode() == b.getLongVersionCode()
+                            && Objects.equals(a.getPackageName(), b.getPackageName());
+                }
+
+                @Override
+                public String toString() {
+                    return "is the same as";
+                }
+            };
+
+    private static final Correspondence<PackageRollbackInfo.RestoreInfo,
+            PackageRollbackInfo.RestoreInfo>
+            RESTORE_INFO_CORR =
+            new Correspondence<PackageRollbackInfo.RestoreInfo, PackageRollbackInfo.RestoreInfo>() {
+                @Override
+                public boolean compare(PackageRollbackInfo.RestoreInfo a,
+                        PackageRollbackInfo.RestoreInfo b) {
+                    if (a == null || b == null) {
+                        return a == b;
+                    }
+                    return a.userId == b.userId
+                            && a.appId == b.appId
+                            && Objects.equals(a.seInfo, b.seInfo);
+                }
+
+                @Override
+                public String toString() {
+                    return "is the same as";
+                }
+            };
+
+    private static final String JSON_ROLLBACK = "{'info':{'rollbackId':123,'packages':"
+            + "[{'versionRolledBackFrom':{'packageName':'blah','longVersionCode':55},"
+            + "'versionRolledBackTo':{'packageName':'blah1','longVersionCode':50},'pendingBackups':"
+            + "[59,1245,124544],'pendingRestores':[{'userId':498,'appId':32322,'seInfo':'wombles'},"
+            + "{'userId':-895,'appId':1,'seInfo':'pingu'}],'isApex':false,'installedUsers':"
+            + "[498468432,1111,98464],'ceSnapshotInodes':[{'userId':1,'ceSnapshotInode':-6},"
+            + "{'userId':2222,'ceSnapshotInode':81641654445},{'userId':546546,"
+            + "'ceSnapshotInode':345689375}]},{'versionRolledBackFrom':{'packageName':'chips',"
+            + "'longVersionCode':28},'versionRolledBackTo':{'packageName':'com.chips.test',"
+            + "'longVersionCode':48},'pendingBackups':[5],'pendingRestores':[{'userId':18,"
+            + "'appId':-12,'seInfo':''}],'isApex':false,'installedUsers':[55,79],"
+            + "'ceSnapshotInodes':[]}],'isStaged':false,'causePackages':[{'packageName':'hello',"
+            + "'longVersionCode':23},{'packageName':'something','longVersionCode':999}],"
+            + "'committedSessionId':45654465},'timestamp':'2019-10-01T12:29:08.855Z',"
+            + "'stagedSessionId':-1,'state':'enabling','apkSessionId':-1,"
+            + "'restoreUserDataInProgress':true}";
+
+    @Rule
+    public TemporaryFolder mFolder = new TemporaryFolder();
+
+    private File mRollbackDir;
+
+    private RollbackStore mRollbackStore;
+
+    @Before
+    public void setUp() throws Exception {
+        mRollbackStore = new RollbackStore(mFolder.getRoot());
+        mRollbackDir = mFolder.newFolder(ID + "");
+        mFolder.newFile("rollback.json");
+    }
+
+    @Test
+    public void createNonStaged() {
+        Rollback rollback = mRollbackStore.createNonStagedRollback(ID);
+
+        assertThat(rollback.getBackupDir().getAbsolutePath())
+                .isEqualTo(mFolder.getRoot().getAbsolutePath() + "/" + ID);
+
+        assertThat(rollback.isStaged()).isFalse();
+        assertThat(rollback.info.getRollbackId()).isEqualTo(ID);
+        assertThat(rollback.info.getPackages()).isEmpty();
+        assertThat(rollback.isEnabling()).isTrue();
+    }
+
+    @Test
+    public void createStaged() {
+        Rollback rollback = mRollbackStore.createStagedRollback(ID, 897);
+
+        assertThat(rollback.getBackupDir().getAbsolutePath())
+                .isEqualTo(mFolder.getRoot().getAbsolutePath() + "/" + ID);
+
+        assertThat(rollback.isStaged()).isTrue();
+        assertThat(rollback.getStagedSessionId()).isEqualTo(897);
+
+        assertThat(rollback.info.getRollbackId()).isEqualTo(ID);
+        assertThat(rollback.info.getPackages()).isEmpty();
+        assertThat(rollback.isEnabling()).isTrue();
+    }
+
+    @Test
+    public void saveAndLoadRollback() {
+        Rollback origRb = mRollbackStore.createNonStagedRollback(ID);
+
+        origRb.setRestoreUserDataInProgress(true);
+        origRb.info.getCausePackages().add(new VersionedPackage("com.made.up", 2));
+        origRb.info.getCausePackages().add(new VersionedPackage("com.pack.age", 99));
+        origRb.info.setCommittedSessionId(123456);
+
+        PackageRollbackInfo pkgInfo1 =
+                new PackageRollbackInfo(new VersionedPackage("com.made.up", 18),
+                        new VersionedPackage("com.something.else", 5), new IntArray(),
+                        new ArrayList<>(), false, new IntArray(), new SparseLongArray());
+        pkgInfo1.getPendingBackups().add(8);
+        pkgInfo1.getPendingBackups().add(888);
+        pkgInfo1.getPendingBackups().add(88885);
+        pkgInfo1.getCeSnapshotInodes().put(12, 424);
+        pkgInfo1.getCeSnapshotInodes().put(222772, 10000000000L);
+        pkgInfo1.getCeSnapshotInodes().put(10, -67);
+
+        pkgInfo1.getPendingRestores().add(
+                new PackageRollbackInfo.RestoreInfo(4980, 3442322, "seInfo"));
+        pkgInfo1.getPendingRestores().add(
+                new PackageRollbackInfo.RestoreInfo(-89, 15, "otherSeInfo"));
+
+        pkgInfo1.getSnapshottedUsers().add(11);
+        pkgInfo1.getSnapshottedUsers().add(1);
+        pkgInfo1.getSnapshottedUsers().add(0);
+
+        PackageRollbackInfo pkgInfo2 = new PackageRollbackInfo(
+                new VersionedPackage("another.package", 2),
+                new VersionedPackage("com.test.ing", 48888), new IntArray(), new ArrayList<>(),
+                false, new IntArray(), new SparseLongArray());
+        pkgInfo2.getPendingBackups().add(57);
+
+        pkgInfo2.getPendingRestores().add(
+                new PackageRollbackInfo.RestoreInfo(180, -120, ""));
+
+        origRb.info.getPackages().add(pkgInfo1);
+        origRb.info.getPackages().add(pkgInfo2);
+
+        RollbackStore.saveRollback(origRb);
+
+        List<Rollback> loadedRollbacks = mRollbackStore.loadRollbacks();
+        assertThat(loadedRollbacks).hasSize(1);
+        Rollback loadedRb = loadedRollbacks.get(0);
+
+        assertRollbacksAreEquivalent(loadedRb, origRb);
+    }
+
+    @Test
+    public void loadFromJson() throws Exception {
+        Rollback expectedRb = mRollbackStore.createNonStagedRollback(ID);
+
+        expectedRb.setTimestamp(Instant.parse("2019-10-01T12:29:08.855Z"));
+        expectedRb.setRestoreUserDataInProgress(true);
+        expectedRb.info.getCausePackages().add(new VersionedPackage("hello", 23));
+        expectedRb.info.getCausePackages().add(new VersionedPackage("something", 999));
+        expectedRb.info.setCommittedSessionId(45654465);
+
+        PackageRollbackInfo pkgInfo1 = new PackageRollbackInfo(new VersionedPackage("blah", 55),
+                new VersionedPackage("blah1", 50), new IntArray(), new ArrayList<>(),
+                false, new IntArray(), new SparseLongArray());
+        pkgInfo1.getPendingBackups().add(59);
+        pkgInfo1.getPendingBackups().add(1245);
+        pkgInfo1.getPendingBackups().add(124544);
+        pkgInfo1.getCeSnapshotInodes().put(546546, 345689375);
+        pkgInfo1.getCeSnapshotInodes().put(2222, 81641654445L);
+        pkgInfo1.getCeSnapshotInodes().put(1, -6);
+
+        pkgInfo1.getPendingRestores().add(
+                new PackageRollbackInfo.RestoreInfo(498, 32322, "wombles"));
+        pkgInfo1.getPendingRestores().add(
+                new PackageRollbackInfo.RestoreInfo(-895, 1, "pingu"));
+
+        pkgInfo1.getSnapshottedUsers().add(498468432);
+        pkgInfo1.getSnapshottedUsers().add(1111);
+        pkgInfo1.getSnapshottedUsers().add(98464);
+
+        PackageRollbackInfo pkgInfo2 = new PackageRollbackInfo(new VersionedPackage("chips", 28),
+                new VersionedPackage("com.chips.test", 48), new IntArray(), new ArrayList<>(),
+                false, new IntArray(), new SparseLongArray());
+        pkgInfo2.getPendingBackups().add(5);
+
+        pkgInfo2.getPendingRestores().add(
+                new PackageRollbackInfo.RestoreInfo(18, -12, ""));
+
+        pkgInfo2.getSnapshottedUsers().add(55);
+        pkgInfo2.getSnapshottedUsers().add(79);
+
+        expectedRb.info.getPackages().add(pkgInfo1);
+        expectedRb.info.getPackages().add(pkgInfo2);
+
+        Rollback parsedRb = RollbackStore.rollbackFromJson(
+                new JSONObject(JSON_ROLLBACK), expectedRb.getBackupDir());
+
+        assertRollbacksAreEquivalent(parsedRb, expectedRb);
+    }
+
+    @Test
+    public void saveAndDelete() {
+        Rollback rollback = mRollbackStore.createNonStagedRollback(ID);
+
+        RollbackStore.saveRollback(rollback);
+
+        File expectedFile = new File(mRollbackDir.getAbsolutePath() + "/rollback.json");
+
+        assertThat(expectedFile.exists()).isTrue();
+
+        RollbackStore.deleteRollback(rollback);
+
+        assertThat(expectedFile.exists()).isFalse();
+    }
+
+    private void assertRollbacksAreEquivalent(Rollback b, Rollback a) {
+        assertThat(b.info.getRollbackId()).isEqualTo(ID);
+
+        assertThat(b.getBackupDir()).isEqualTo(a.getBackupDir());
+
+        assertThat(b.isRestoreUserDataInProgress())
+                .isEqualTo(a.isRestoreUserDataInProgress());
+
+        assertThat(b.getTimestamp()).isEqualTo(a.getTimestamp());
+
+        assertThat(b.isEnabling()).isEqualTo(a.isEnabling());
+        assertThat(b.isAvailable()).isEqualTo(a.isAvailable());
+        assertThat(b.isCommitted()).isEqualTo(a.isCommitted());
+
+        assertThat(b.isStaged()).isEqualTo(a.isStaged());
+
+        assertThat(b.getApexPackageNames())
+                .containsExactlyElementsIn(a.getApexPackageNames());
+
+        assertThat(b.getStagedSessionId()).isEqualTo(a.getStagedSessionId());
+
+        assertThat(b.info.getCommittedSessionId()).isEqualTo(a.info.getCommittedSessionId());
+
+        assertThat(b.info.getCausePackages()).comparingElementsUsing(VER_PKG_CORR)
+                .containsExactlyElementsIn(a.info.getCausePackages());
+
+        assertThat(b.info.getPackages()).hasSize(a.info.getPackages().size());
+
+        for (int i = 0; i < b.info.getPackages().size(); i++) {
+            assertPackageRollbacksAreEquivalent(
+                    b.info.getPackages().get(i), a.info.getPackages().get(i));
+        }
+    }
+
+    private void assertPackageRollbacksAreEquivalent(PackageRollbackInfo b, PackageRollbackInfo a) {
+        assertThat(b.getPackageName()).isEqualTo(a.getPackageName());
+
+        assertThat(b.getVersionRolledBackFrom().getLongVersionCode())
+                .isEqualTo(a.getVersionRolledBackFrom().getLongVersionCode());
+        assertThat(b.getVersionRolledBackFrom().getPackageName())
+                .isEqualTo(a.getVersionRolledBackFrom().getPackageName());
+
+        assertThat(b.getVersionRolledBackTo().getLongVersionCode())
+                .isEqualTo(a.getVersionRolledBackTo().getLongVersionCode());
+        assertThat(b.getVersionRolledBackTo().getPackageName())
+                .isEqualTo(a.getVersionRolledBackTo().getPackageName());
+
+        assertThat(b.getPendingBackups().toArray()).isEqualTo(a.getPendingBackups().toArray());
+
+        assertThat(b.getPendingRestores()).comparingElementsUsing(RESTORE_INFO_CORR)
+                .containsExactlyElementsIn(a.getPendingRestores());
+
+        assertThat(b.isApex()).isEqualTo(a.isApex());
+
+        assertThat(b.getSnapshottedUsers().toArray()).isEqualTo(a.getSnapshottedUsers().toArray());
+
+        assertThat(b.getCeSnapshotInodes().toString())
+                .isEqualTo(a.getCeSnapshotInodes().toString());
+    }
+
+}
diff --git a/services/tests/uiservicestests/src/com/android/server/notification/GroupHelperTest.java b/services/tests/uiservicestests/src/com/android/server/notification/GroupHelperTest.java
index f652c5a..721641a 100644
--- a/services/tests/uiservicestests/src/com/android/server/notification/GroupHelperTest.java
+++ b/services/tests/uiservicestests/src/com/android/server/notification/GroupHelperTest.java
@@ -15,6 +15,8 @@
  */
 package com.android.server.notification;
 
+import static com.android.server.notification.GroupHelper.AUTOGROUP_KEY;
+
 import static junit.framework.Assert.assertEquals;
 import static junit.framework.Assert.assertNotNull;
 
@@ -155,6 +157,196 @@
     }
 
     @Test
+    public void testAutoGroupCount_addingNoGroupSBN() {
+        final String pkg = "package";
+        ArrayList<StatusBarNotification>  notifications = new ArrayList<>();
+        for (int i = 0; i < AUTOGROUP_AT_COUNT + 1; i++) {
+            notifications.add(getSbn(pkg, i, String.valueOf(i), UserHandle.SYSTEM));
+        }
+
+        for (StatusBarNotification sbn: notifications) {
+            sbn.getNotification().flags |= Notification.FLAG_ONGOING_EVENT;
+            sbn.setOverrideGroupKey(AUTOGROUP_KEY);
+        }
+
+        for (StatusBarNotification sbn: notifications) {
+            mGroupHelper.onNotificationPosted(sbn, true);
+        }
+
+        verify(mCallback, times(AUTOGROUP_AT_COUNT + 1))
+            .updateAutogroupSummary(anyString(), eq(true));
+
+        int userId = UserHandle.SYSTEM.getIdentifier();
+        assertEquals(mGroupHelper.getOngoingGroupCount(
+                userId, pkg, AUTOGROUP_KEY), AUTOGROUP_AT_COUNT + 1);
+    }
+
+    @Test
+    public void testAutoGroupCount_UpdateNotification() {
+        final String pkg = "package";
+        ArrayList<StatusBarNotification>  notifications = new ArrayList<>();
+        for (int i = 0; i < AUTOGROUP_AT_COUNT + 1; i++) {
+            notifications.add(getSbn(pkg, i, String.valueOf(i), UserHandle.SYSTEM));
+        }
+
+        for (StatusBarNotification sbn: notifications) {
+            sbn.getNotification().flags |= Notification.FLAG_ONGOING_EVENT;
+            sbn.setOverrideGroupKey(AUTOGROUP_KEY);
+        }
+
+        for (StatusBarNotification sbn: notifications) {
+            mGroupHelper.onNotificationPosted(sbn, true);
+        }
+
+        notifications.get(0).getNotification().flags &= ~Notification.FLAG_ONGOING_EVENT;
+
+        mGroupHelper.onNotificationUpdated(notifications.get(0), true);
+
+        verify(mCallback, times(AUTOGROUP_AT_COUNT + 2))
+                .updateAutogroupSummary(anyString(), eq(true));
+
+        int userId = UserHandle.SYSTEM.getIdentifier();
+        assertEquals(mGroupHelper.getOngoingGroupCount(
+                userId, pkg, AUTOGROUP_KEY), AUTOGROUP_AT_COUNT);
+    }
+
+    @Test
+    public void testAutoGroupCount_UpdateNotificationAfterChanges() {
+        final String pkg = "package";
+        ArrayList<StatusBarNotification>  notifications = new ArrayList<>();
+        for (int i = 0; i < AUTOGROUP_AT_COUNT + 1; i++) {
+            notifications.add(getSbn(pkg, i, String.valueOf(i), UserHandle.SYSTEM));
+        }
+
+        for (StatusBarNotification sbn: notifications) {
+            sbn.getNotification().flags |= Notification.FLAG_ONGOING_EVENT;
+            sbn.setOverrideGroupKey(AUTOGROUP_KEY);
+        }
+
+        for (StatusBarNotification sbn: notifications) {
+            mGroupHelper.onNotificationPosted(sbn, true);
+        }
+
+        notifications.get(0).getNotification().flags &= ~Notification.FLAG_ONGOING_EVENT;
+
+        mGroupHelper.onNotificationUpdated(notifications.get(0), true);
+
+        notifications.get(0).getNotification().flags |= Notification.FLAG_ONGOING_EVENT;
+
+        mGroupHelper.onNotificationUpdated(notifications.get(0), true);
+
+        verify(mCallback, times(AUTOGROUP_AT_COUNT + 3))
+                .updateAutogroupSummary(anyString(), eq(true));
+
+        int userId = UserHandle.SYSTEM.getIdentifier();
+        assertEquals(mGroupHelper.getOngoingGroupCount(
+                userId, pkg, AUTOGROUP_KEY), AUTOGROUP_AT_COUNT + 1);
+    }
+
+    @Test
+    public void testAutoGroupCount_RemoveNotification() {
+        final String pkg = "package";
+        ArrayList<StatusBarNotification>  notifications = new ArrayList<>();
+        for (int i = 0; i < AUTOGROUP_AT_COUNT + 1; i++) {
+            notifications.add(getSbn(pkg, i, String.valueOf(i), UserHandle.SYSTEM));
+        }
+
+        for (StatusBarNotification sbn: notifications) {
+            sbn.getNotification().flags |= Notification.FLAG_ONGOING_EVENT;
+            sbn.setOverrideGroupKey(AUTOGROUP_KEY);
+        }
+
+        for (StatusBarNotification sbn: notifications) {
+            mGroupHelper.onNotificationPosted(sbn, true);
+        }
+
+        mGroupHelper.onNotificationRemoved(notifications.get(0));
+
+        verify(mCallback, times(AUTOGROUP_AT_COUNT + 2))
+                .updateAutogroupSummary(anyString(), eq(true));
+
+        int userId = UserHandle.SYSTEM.getIdentifier();
+        assertEquals(mGroupHelper.getOngoingGroupCount(
+                userId, pkg, AUTOGROUP_KEY), AUTOGROUP_AT_COUNT);
+    }
+
+
+    @Test
+    public void testAutoGroupCount_UpdateToNoneOngoingNotification() {
+        final String pkg = "package";
+        ArrayList<StatusBarNotification>  notifications = new ArrayList<>();
+        for (int i = 0; i < AUTOGROUP_AT_COUNT + 1; i++) {
+            notifications.add(getSbn(pkg, i, String.valueOf(i), UserHandle.SYSTEM));
+        }
+
+        for (StatusBarNotification sbn: notifications) {
+            sbn.setOverrideGroupKey(AUTOGROUP_KEY);
+        }
+
+        for (StatusBarNotification sbn: notifications) {
+            mGroupHelper.onNotificationPosted(sbn, true);
+        }
+
+        notifications.get(0).getNotification().flags |= Notification.FLAG_ONGOING_EVENT;
+        mGroupHelper.onNotificationUpdated(notifications.get(0), true);
+
+        verify(mCallback, times(1))
+                .updateAutogroupSummary(anyString(), eq(true));
+
+        int userId = UserHandle.SYSTEM.getIdentifier();
+        assertEquals(mGroupHelper.getOngoingGroupCount(
+                userId, pkg, AUTOGROUP_KEY), 1);
+    }
+
+    @Test
+    public void testAutoGroupCount_AddOneOngoingNotification() {
+        final String pkg = "package";
+        ArrayList<StatusBarNotification>  notifications = new ArrayList<>();
+        for (int i = 0; i < AUTOGROUP_AT_COUNT + 1; i++) {
+            notifications.add(getSbn(pkg, i, String.valueOf(i), UserHandle.SYSTEM));
+        }
+        StatusBarNotification sbn = notifications.get(0);
+        sbn.getNotification().flags |= Notification.FLAG_ONGOING_EVENT;
+        sbn.setOverrideGroupKey(AUTOGROUP_KEY);
+
+
+        for (StatusBarNotification current: notifications) {
+            mGroupHelper.onNotificationPosted(current, true);
+        }
+
+        verify(mCallback, times(1))
+                .updateAutogroupSummary(anyString(), eq(true));
+
+        int userId = UserHandle.SYSTEM.getIdentifier();
+        assertEquals(mGroupHelper.getOngoingGroupCount(
+                userId, pkg, AUTOGROUP_KEY), 1);
+    }
+
+    @Test
+    public void testAutoGroupCount_UpdateNoneOngoing() {
+        final String pkg = "package";
+        ArrayList<StatusBarNotification>  notifications = new ArrayList<>();
+        for (int i = 0; i < AUTOGROUP_AT_COUNT + 1; i++) {
+            notifications.add(getSbn(pkg, i, String.valueOf(i), UserHandle.SYSTEM));
+        }
+
+        for (StatusBarNotification sbn: notifications) {
+            sbn.setOverrideGroupKey(AUTOGROUP_KEY);
+        }
+
+        for (StatusBarNotification sbn: notifications) {
+            mGroupHelper.onNotificationPosted(sbn, true);
+        }
+
+        verify(mCallback, times(0))
+                .updateAutogroupSummary(anyString(), eq(true));
+
+        int userId = UserHandle.SYSTEM.getIdentifier();
+        assertEquals(mGroupHelper.getOngoingGroupCount(userId, pkg, AUTOGROUP_KEY), 0);
+    }
+
+
+    @Test
     public void testDropToZeroRemoveGroup() throws Exception {
         final String pkg = "package";
         List<StatusBarNotification> posted = new ArrayList<>();
diff --git a/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java b/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java
old mode 100644
new mode 100755
index 2de8d05..4ea2fc0
--- a/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java
+++ b/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java
@@ -44,6 +44,7 @@
 import static android.content.pm.PackageManager.PERMISSION_GRANTED;
 import static android.os.Build.VERSION_CODES.O_MR1;
 import static android.os.Build.VERSION_CODES.P;
+import static android.os.UserHandle.USER_SYSTEM;
 import static android.service.notification.Adjustment.KEY_IMPORTANCE;
 import static android.service.notification.Adjustment.KEY_USER_SENTIMENT;
 import static android.service.notification.NotificationListenerService.Ranking.USER_SENTIMENT_NEGATIVE;
@@ -129,6 +130,7 @@
 import android.testing.TestableLooper;
 import android.testing.TestableLooper.RunWithLooper;
 import android.testing.TestablePermissions;
+import android.testing.TestableResources;
 import android.text.Html;
 import android.util.ArrayMap;
 import android.util.ArraySet;
@@ -1180,6 +1182,36 @@
     }
 
     @Test
+    public void testAutobundledSummary_notificationAdded() {
+        NotificationRecord summary =
+                generateNotificationRecord(mTestNotificationChannel, 0, "pkg", true);
+        summary.getNotification().flags |= Notification.FLAG_AUTOGROUP_SUMMARY;
+        mService.addNotification(summary);
+        mService.mSummaryByGroupKey.put("pkg", summary);
+        mService.mAutobundledSummaries.put(0, new ArrayMap<>());
+        mService.mAutobundledSummaries.get(0).put("pkg", summary.getKey());
+        mService.updateAutobundledSummaryFlags(0, "pkg", true);
+
+        assertTrue(summary.sbn.isOngoing());
+    }
+
+    @Test
+    public void testAutobundledSummary_notificationRemoved() {
+        NotificationRecord summary =
+                generateNotificationRecord(mTestNotificationChannel, 0, "pkg", true);
+        summary.getNotification().flags |= Notification.FLAG_AUTOGROUP_SUMMARY;
+        summary.getNotification().flags |= Notification.FLAG_ONGOING_EVENT;
+        mService.addNotification(summary);
+        mService.mAutobundledSummaries.put(0, new ArrayMap<>());
+        mService.mAutobundledSummaries.get(0).put("pkg", summary.getKey());
+        mService.mSummaryByGroupKey.put("pkg", summary);
+
+        mService.updateAutobundledSummaryFlags(0, "pkg", false);
+
+        assertFalse(summary.sbn.isOngoing());
+    }
+
+    @Test
     public void testCancelAllNotifications_IgnoreForegroundService() throws Exception {
         final StatusBarNotification sbn = generateNotificationRecord(null).sbn;
         sbn.getNotification().flags |= FLAG_FOREGROUND_SERVICE;
@@ -3278,7 +3310,7 @@
     @Test
     public void testRestore() throws Exception {
         int systemChecks = mService.countSystemChecks;
-        mBinderService.applyRestore(null, UserHandle.USER_SYSTEM);
+        mBinderService.applyRestore(null, USER_SYSTEM);
         assertEquals(1, mService.countSystemChecks - systemChecks);
     }
 
@@ -3347,7 +3379,7 @@
         reset(mUgmInternal);
         when(mUgmInternal.newUriPermissionOwner(any())).thenReturn(new Binder());
         mService.updateUriPermissions(recordA, null, mContext.getPackageName(),
-                UserHandle.USER_SYSTEM);
+                USER_SYSTEM);
         verify(mUgm, times(1)).grantUriPermissionFromOwner(any(), anyInt(), any(),
                 eq(message1.getDataUri()), anyInt(), anyInt(), anyInt());
         verify(mUgm, times(1)).grantUriPermissionFromOwner(any(), anyInt(), any(),
@@ -3363,21 +3395,21 @@
         // Update means we drop access to first
         reset(mUgmInternal);
         mService.updateUriPermissions(recordB, recordA, mContext.getPackageName(),
-                UserHandle.USER_SYSTEM);
+                USER_SYSTEM);
         verify(mUgmInternal, times(1)).revokeUriPermissionFromOwner(any(),
                 eq(message1.getDataUri()), anyInt(), anyInt());
 
         // Update back means we grant access to first again
         reset(mUgm);
         mService.updateUriPermissions(recordA, recordB, mContext.getPackageName(),
-                UserHandle.USER_SYSTEM);
+                USER_SYSTEM);
         verify(mUgm, times(1)).grantUriPermissionFromOwner(any(), anyInt(), any(),
                 eq(message1.getDataUri()), anyInt(), anyInt(), anyInt());
 
         // And update to empty means we drop everything
         reset(mUgmInternal);
         mService.updateUriPermissions(null, recordB, mContext.getPackageName(),
-                UserHandle.USER_SYSTEM);
+                USER_SYSTEM);
         verify(mUgmInternal, times(1)).revokeUriPermissionFromOwner(any(), eq(null),
                 anyInt(), anyInt());
     }
@@ -3864,7 +3896,9 @@
         mService.simulatePackageDistractionBroadcast(
                 PackageManager.RESTRICTION_HIDE_NOTIFICATIONS, new String[] {"a", "b"});
         ArgumentCaptor<List<NotificationRecord>> captorHide = ArgumentCaptor.forClass(List.class);
-        verify(mListeners, times(2)).notifyHiddenLocked(captorHide.capture());
+
+        // should be called only once.
+        verify(mListeners, times(1)).notifyHiddenLocked(captorHide.capture());
         assertEquals(2, captorHide.getValue().size());
         assertEquals("a", captorHide.getValue().get(0).sbn.getPackageName());
         assertEquals("b", captorHide.getValue().get(1).sbn.getPackageName());
@@ -3873,7 +3907,9 @@
         mService.simulatePackageDistractionBroadcast(
                 PackageManager.RESTRICTION_HIDE_FROM_SUGGESTIONS, new String[] {"a", "b"});
         ArgumentCaptor<List<NotificationRecord>> captorUnhide = ArgumentCaptor.forClass(List.class);
-        verify(mListeners, times(2)).notifyUnhiddenLocked(captorUnhide.capture());
+
+        // should be called only once.
+        verify(mListeners, times(1)).notifyUnhiddenLocked(captorUnhide.capture());
         assertEquals(2, captorUnhide.getValue().size());
         assertEquals("a", captorUnhide.getValue().get(0).sbn.getPackageName());
         assertEquals("b", captorUnhide.getValue().get(1).sbn.getPackageName());
@@ -4073,7 +4109,7 @@
     public void testIsCallerInstantApp_userAllNotification() throws Exception {
         ApplicationInfo info = new ApplicationInfo();
         info.privateFlags = ApplicationInfo.PRIVATE_FLAG_INSTANT;
-        when(mPackageManager.getApplicationInfo(anyString(), anyInt(), eq(UserHandle.USER_SYSTEM)))
+        when(mPackageManager.getApplicationInfo(anyString(), anyInt(), eq(USER_SYSTEM)))
                 .thenReturn(info);
         when(mPackageManager.getPackagesForUid(anyInt())).thenReturn(new String[]{"any"});
 
@@ -5662,4 +5698,33 @@
         StatusBarNotification[] notifsAfter = mBinderService.getActiveNotifications(PKG);
         assertEquals(1, notifsAfter.length);
     }
+
+    @Test
+    public void testLoadDefaultApprovedServices_emptyResources() {
+        TestableResources tr = mContext.getOrCreateTestableResources();
+        tr.addOverride(com.android.internal.R.string.config_defaultListenerAccessPackages, "");
+        tr.addOverride(com.android.internal.R.string.config_defaultDndAccessPackages, "");
+        tr.addOverride(com.android.internal.R.string.config_defaultAssistantAccessComponent, "");
+        setDefaultAssistantInDeviceConfig("");
+
+        mService.loadDefaultApprovedServices(USER_SYSTEM);
+
+        verify(mListeners, never()).addDefaultComponentOrPackage(anyString());
+        verify(mConditionProviders, never()).addDefaultComponentOrPackage(anyString());
+        verify(mAssistants, never()).addDefaultComponentOrPackage(anyString());
+    }
+
+    @Test
+    public void testLoadDefaultApprovedServices_dnd() {
+        TestableResources tr = mContext.getOrCreateTestableResources();
+        tr.addOverride(com.android.internal.R.string.config_defaultDndAccessPackages, "test");
+        when(mListeners.queryPackageForServices(anyString(), anyInt(), anyInt()))
+                .thenReturn(new ArraySet<>());
+
+        mService.loadDefaultApprovedServices(USER_SYSTEM);
+
+        verify(mConditionProviders, times(1)).addDefaultComponentOrPackage("test");
+    }
+
+    // TODO: add tests for the rest of the non-empty cases
 }
diff --git a/services/tests/wmtests/src/com/android/server/wm/ActivityDisplayTests.java b/services/tests/wmtests/src/com/android/server/wm/ActivityDisplayTests.java
index 69cc9b2..fff3221 100644
--- a/services/tests/wmtests/src/com/android/server/wm/ActivityDisplayTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/ActivityDisplayTests.java
@@ -317,24 +317,24 @@
         doAnswer(invocation -> {
             display.positionChildAtTop(stack3, false);
             return true;
-        }).when(mSupervisor).removeTaskByIdLocked(eq(task4.taskId), anyBoolean(), anyBoolean(),
+        }).when(mSupervisor).removeTaskByIdLocked(eq(task4.mTaskId), anyBoolean(), anyBoolean(),
                 any());
 
         // Removing stacks from the display while removing stacks.
         doAnswer(invocation -> {
             display.removeChild(stack2);
             return true;
-        }).when(mSupervisor).removeTaskByIdLocked(eq(task2.taskId), anyBoolean(), anyBoolean(),
+        }).when(mSupervisor).removeTaskByIdLocked(eq(task2.mTaskId), anyBoolean(), anyBoolean(),
                 any());
 
         runnable.run();
-        verify(mSupervisor).removeTaskByIdLocked(eq(task4.taskId), anyBoolean(), anyBoolean(),
+        verify(mSupervisor).removeTaskByIdLocked(eq(task4.mTaskId), anyBoolean(), anyBoolean(),
                 any());
-        verify(mSupervisor).removeTaskByIdLocked(eq(task3.taskId), anyBoolean(), anyBoolean(),
+        verify(mSupervisor).removeTaskByIdLocked(eq(task3.mTaskId), anyBoolean(), anyBoolean(),
                 any());
-        verify(mSupervisor).removeTaskByIdLocked(eq(task2.taskId), anyBoolean(), anyBoolean(),
+        verify(mSupervisor).removeTaskByIdLocked(eq(task2.mTaskId), anyBoolean(), anyBoolean(),
                 any());
-        verify(mSupervisor).removeTaskByIdLocked(eq(task1.taskId), anyBoolean(), anyBoolean(),
+        verify(mSupervisor).removeTaskByIdLocked(eq(task1.mTaskId), anyBoolean(), anyBoolean(),
                 any());
     }
 
diff --git a/services/tests/wmtests/src/com/android/server/wm/ActivityRecordTests.java b/services/tests/wmtests/src/com/android/server/wm/ActivityRecordTests.java
index 50203df..bf1508a 100644
--- a/services/tests/wmtests/src/com/android/server/wm/ActivityRecordTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/ActivityRecordTests.java
@@ -287,22 +287,6 @@
     }
 
     @Test
-    public void testNotifiesSeqIncrementToAppToken() {
-        final Configuration appWindowTokenRequestedOrientation = mock(Configuration.class);
-        mActivity.mAppWindowToken = mock(AppWindowToken.class);
-        doReturn(appWindowTokenRequestedOrientation).when(mActivity.mAppWindowToken)
-                .getRequestedOverrideConfiguration();
-
-        final Configuration newConfig = new Configuration();
-        newConfig.orientation = ORIENTATION_PORTRAIT;
-
-        final int prevSeq = mActivity.getMergedOverrideConfiguration().seq;
-        mActivity.onRequestedOverrideConfigurationChanged(newConfig);
-        assertEquals(prevSeq + 1, appWindowTokenRequestedOrientation.seq);
-        verify(mActivity.mAppWindowToken).onMergedOverrideConfigurationChanged();
-    }
-
-    @Test
     public void testSetsRelaunchReason_NotDragResizing() {
         mActivity.setState(ActivityStack.ActivityState.RESUMED, "Testing");
 
@@ -519,7 +503,7 @@
                 anyInt() /* height */, any() /* displayCutout */, any() /* outInsets */);
 
         doReturn(ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED)
-                .when(mActivity.mAppWindowToken).getOrientationIgnoreVisibility();
+                .when(mActivity).getRequestedOrientation();
         mActivity.info.resizeMode = RESIZE_MODE_UNRESIZEABLE;
         mActivity.info.minAspectRatio = mActivity.info.maxAspectRatio = 1;
         ensureActivityConfiguration();
@@ -571,7 +555,7 @@
         // Move the non-resizable activity to the new display.
         mStack.reparent(newDisplay, true /* onTop */, false /* displayRemoved */);
 
-        assertEquals(originalBounds, mActivity.getBounds());
+        assertEquals(originalBounds, mActivity.getWindowConfiguration().getBounds());
         assertEquals(originalDpi, mActivity.getConfiguration().densityDpi);
         assertTrue(mActivity.inSizeCompatMode());
     }
@@ -579,7 +563,7 @@
     @Test
     public void testSizeCompatMode_FixedScreenBoundsWhenDisplaySizeChanged() {
         setupDisplayContentForCompatDisplayInsets();
-        when(mActivity.mAppWindowToken.getOrientationIgnoreVisibility()).thenReturn(
+        when(mActivity.getRequestedOrientation()).thenReturn(
                 ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
         mTask.getWindowConfiguration().setAppBounds(mStack.getDisplay().getBounds());
         mTask.getConfiguration().orientation = ORIENTATION_PORTRAIT;
@@ -592,7 +576,7 @@
         setupDisplayAndParentSize(1000, 2000);
         ensureActivityConfiguration();
 
-        assertEquals(originalBounds, mActivity.getBounds());
+        assertEquals(originalBounds, mActivity.getWindowConfiguration().getBounds());
         assertTrue(mActivity.inSizeCompatMode());
     }
 
@@ -627,7 +611,7 @@
         mActivity.visible = false;
         mActivity.app.setReportedProcState(ActivityManager.PROCESS_STATE_CACHED_ACTIVITY);
         // Make the parent bounds to be different so the activity is in size compatibility mode.
-        mTask.getWindowConfiguration().setAppBounds(new Rect(0, 0, 600, 1200));
+        setupDisplayAndParentSize(600, 1200);
 
         // Simulate the display changes orientation.
         doReturn(ActivityInfo.CONFIG_SCREEN_SIZE | CONFIG_ORIENTATION
diff --git a/services/tests/wmtests/src/com/android/server/wm/ActivityStackSupervisorTests.java b/services/tests/wmtests/src/com/android/server/wm/ActivityStackSupervisorTests.java
index 9e1df91..1eeca91 100644
--- a/services/tests/wmtests/src/com/android/server/wm/ActivityStackSupervisorTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/ActivityStackSupervisorTests.java
@@ -127,7 +127,7 @@
         mSupervisor.handleNonResizableTaskIfNeeded(task, newDisplay.getWindowingMode(),
                 newDisplay.mDisplayId, stack);
         // The top activity is unresizable, so it should notify the activity is forced resizing.
-        verify(taskChangeNotifier).notifyActivityForcedResizable(eq(task.taskId),
+        verify(taskChangeNotifier).notifyActivityForcedResizable(eq(task.mTaskId),
                 eq(FORCED_RESIZEABLE_REASON_SECONDARY_DISPLAY),
                 eq(unresizableActivity.packageName));
         reset(taskChangeNotifier);
diff --git a/services/tests/wmtests/src/com/android/server/wm/ActivityStartControllerTests.java b/services/tests/wmtests/src/com/android/server/wm/ActivityStartControllerTests.java
index 5e4c965..11aac3c 100644
--- a/services/tests/wmtests/src/com/android/server/wm/ActivityStartControllerTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/ActivityStartControllerTests.java
@@ -73,7 +73,9 @@
         final Random random = new Random();
 
         final ActivityRecord activity = new ActivityBuilder(mService).build();
-        final ActivityRecord source = new ActivityBuilder(mService).build();
+        final ActivityRecord source = new ActivityBuilder(mService)
+                .setCreateTask(true)
+                .build();
         final int startFlags = random.nextInt();
         final ActivityStack stack = mService.mRootActivityContainer.getDefaultDisplay().createStack(
                 WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_STANDARD, true /* onTop */);
diff --git a/services/tests/wmtests/src/com/android/server/wm/ActivityStarterTests.java b/services/tests/wmtests/src/com/android/server/wm/ActivityStarterTests.java
index 78f3f79..8a9423a 100644
--- a/services/tests/wmtests/src/com/android/server/wm/ActivityStarterTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/ActivityStarterTests.java
@@ -57,6 +57,7 @@
 import static org.mockito.ArgumentMatchers.anyBoolean;
 import static org.mockito.ArgumentMatchers.anyInt;
 import static org.mockito.ArgumentMatchers.anyObject;
+import static org.mockito.ArgumentMatchers.anyString;
 import static org.mockito.ArgumentMatchers.eq;
 
 import android.app.ActivityOptions;
@@ -368,6 +369,7 @@
         doReturn(false).when(mockPackageManager).isPermissionsReviewRequired(any(), anyInt());
         doNothing().when(mockPackageManager).grantImplicitAccess(
                 anyInt(), any(), anyInt(), anyInt());
+        doNothing().when(mockPackageManager).notifyPackageUse(anyString(), anyInt());
 
         final Intent intent = new Intent();
         intent.addFlags(launchFlags);
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 f4d1cbf..77fbdcf 100644
--- a/services/tests/wmtests/src/com/android/server/wm/ActivityTestsBase.java
+++ b/services/tests/wmtests/src/com/android/server/wm/ActivityTestsBase.java
@@ -27,6 +27,7 @@
 import static com.android.dx.mockito.inline.extended.ExtendedMockito.any;
 import static com.android.dx.mockito.inline.extended.ExtendedMockito.anyBoolean;
 import static com.android.dx.mockito.inline.extended.ExtendedMockito.doNothing;
+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;
 
@@ -38,8 +39,10 @@
 import android.content.pm.ActivityInfo;
 import android.content.pm.ApplicationInfo;
 import android.content.res.Configuration;
+import android.os.Build;
 import android.os.UserHandle;
 import android.service.voice.IVoiceInteractionSession;
+import android.util.Pair;
 import android.view.DisplayInfo;
 
 import com.android.server.AttributeCache;
@@ -212,6 +215,23 @@
             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++;
@@ -257,12 +277,10 @@
             if (mTaskRecord != null) {
                 // fullscreen value is normally read from resources in ctor, so for testing we need
                 // to set it somewhere else since we can't mock resources.
-                activity.fullscreen = true;
+                doReturn(true).when(activity).occludesParent();
                 activity.setTask(mTaskRecord);
-                activity.createAppWindowToken();
-                spyOn(activity.mAppWindowToken);
                 // Make visible by default...
-                activity.mAppWindowToken.setHidden(false);
+                activity.setHidden(false);
             }
 
             final WindowProcessController wpc = new WindowProcessController(mService,
@@ -271,6 +289,8 @@
                     mock(WindowProcessListener.class));
             wpc.setThread(mock(IApplicationThread.class));
             activity.setProcess(wpc);
+            doReturn(wpc).when(mService).getProcessController(
+                    activity.processName, activity.info.applicationInfo.uid);
 
             // Resume top activities to make sure all other signals in the system are connected.
             mService.mRootActivityContainer.resumeFocusedStacksTopActivities();
@@ -364,9 +384,10 @@
             intent.setFlags(mFlags);
 
             final TaskRecord task = new TaskRecord(mSupervisor.mService, mTaskId, aInfo,
-                    intent /*intent*/, mVoiceSession, null /*_voiceInteractor*/);
+                    intent /*intent*/, mVoiceSession, null /*_voiceInteractor*/,
+                    null /*taskDescription*/);
             spyOn(task);
-            task.userId = mUserId;
+            task.mUserId = mUserId;
 
             if (mStack != null) {
                 mStack.moveToFront("test");
@@ -375,8 +396,6 @@
                 spyOn(task.mTask);
             }
 
-            task.touchActiveTime();
-
             return task;
         }
     }
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 61dbd67..650a911 100644
--- a/services/tests/wmtests/src/com/android/server/wm/AppChangeTransitionTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/AppChangeTransitionTests.java
@@ -57,7 +57,7 @@
 
     private TaskStack mStack;
     private Task mTask;
-    private WindowTestUtils.TestAppWindowToken mToken;
+    private AppWindowToken mToken;
 
     public void setUpOnDisplay(DisplayContent dc) {
         mStack = createTaskStackOnDisplay(WINDOWING_MODE_UNDEFINED, ACTIVITY_TYPE_STANDARD, dc);
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 49e4c78..72d9bd0 100644
--- a/services/tests/wmtests/src/com/android/server/wm/AppTransitionTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/AppTransitionTests.java
@@ -122,9 +122,9 @@
         final DisplayContent dc2 = createNewDisplay(Display.STATE_ON);
 
         // Create 2 app window tokens to represent 2 activity window.
-        final WindowTestUtils.TestAppWindowToken token1 = createTestAppWindowToken(dc1,
+        final AppWindowToken token1 = createTestAppWindowToken(dc1,
                 WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_STANDARD);
-        final WindowTestUtils.TestAppWindowToken token2 = createTestAppWindowToken(dc2,
+        final AppWindowToken token2 = createTestAppWindowToken(dc2,
                 WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_STANDARD);
 
         token1.allDrawn = true;
@@ -159,7 +159,7 @@
 
         final TaskStack stack1 = createTaskStackOnDisplay(dc1);
         final Task task1 = createTaskInStack(stack1, 0 /* userId */);
-        final WindowTestUtils.TestAppWindowToken token1 =
+        final AppWindowToken token1 =
                 WindowTestUtils.createTestAppWindowToken(dc1);
         task1.addChild(token1, 0);
 
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 8957486..66ba81d 100644
--- a/services/tests/wmtests/src/com/android/server/wm/AppWindowTokenAnimationTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/AppWindowTokenAnimationTests.java
@@ -33,8 +33,6 @@
 import androidx.test.filters.FlakyTest;
 import androidx.test.filters.SmallTest;
 
-import com.android.server.wm.WindowTestUtils.TestAppWindowToken;
-
 import org.junit.Before;
 import org.junit.Test;
 import org.junit.runner.RunWith;
@@ -54,7 +52,7 @@
 @RunWith(WindowTestRunner.class)
 public class AppWindowTokenAnimationTests extends WindowTestsBase {
 
-    private TestAppWindowToken mToken;
+    private AppWindowToken mToken;
 
     @Mock
     private AnimationAdapter mSpec;
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 d528e41..2661735 100644
--- a/services/tests/wmtests/src/com/android/server/wm/AppWindowTokenTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/AppWindowTokenTests.java
@@ -53,7 +53,6 @@
 import android.content.res.Configuration;
 import android.graphics.Rect;
 import android.platform.test.annotations.Presubmit;
-import android.view.Display;
 import android.view.Surface;
 import android.view.WindowManager;
 
@@ -78,7 +77,7 @@
 
     TaskStack mStack;
     Task mTask;
-    WindowTestUtils.TestAppWindowToken mToken;
+    AppWindowToken mToken;
 
     private final String mPackageName = getInstrumentation().getTargetContext().getPackageName();
 
@@ -94,7 +93,7 @@
     @Test
     @Presubmit
     public void testAddWindow_Order() {
-        assertEquals(0, mToken.getWindowsCount());
+        assertEquals(0, mToken.getChildCount());
 
         final WindowState win1 = createWindow(null, TYPE_APPLICATION, mToken, "win1");
         final WindowState startingWin = createWindow(null, TYPE_APPLICATION_STARTING, mToken,
@@ -103,17 +102,17 @@
         final WindowState win4 = createWindow(null, TYPE_APPLICATION, mToken, "win4");
 
         // Should not contain the windows that were added above.
-        assertEquals(4, mToken.getWindowsCount());
-        assertTrue(mToken.hasWindow(win1));
-        assertTrue(mToken.hasWindow(startingWin));
-        assertTrue(mToken.hasWindow(baseWin));
-        assertTrue(mToken.hasWindow(win4));
+        assertEquals(4, mToken.getChildCount());
+        assertTrue(mToken.mChildren.contains(win1));
+        assertTrue(mToken.mChildren.contains(startingWin));
+        assertTrue(mToken.mChildren.contains(baseWin));
+        assertTrue(mToken.mChildren.contains(win4));
 
         // The starting window should be on-top of all other windows.
-        assertEquals(startingWin, mToken.getLastChild());
+        assertEquals(startingWin, mToken.mChildren.peekLast());
 
         // The base application window should be below all other windows.
-        assertEquals(baseWin, mToken.getFirstChild());
+        assertEquals(baseWin, mToken.mChildren.peekFirst());
         mToken.removeImmediately();
     }
 
@@ -222,7 +221,7 @@
         containerBounds.set(0, 0, 600, 800);
         mToken.onConfigurationChanged(newParentConfig);
 
-        assertTrue(mToken.inSizeCompatMode());
+        assertTrue(mToken.hasSizeCompatBounds());
         assertEquals(containerAppBounds, mToken.getBounds());
         assertEquals((float) containerAppBounds.width() / fixedBounds.width(),
                 mToken.getSizeCompatScale(), 0.0001f /* delta */);
@@ -232,7 +231,7 @@
         containerBounds.set(containerAppBounds);
         mToken.onConfigurationChanged(newParentConfig);
 
-        assertTrue(mToken.inSizeCompatMode());
+        assertTrue(mToken.hasSizeCompatBounds());
         // Don't scale up, so the bounds keep the same as the fixed width.
         assertEquals(fixedBounds.width(), mToken.getBounds().width());
         // Assert the position is horizontal center.
@@ -244,7 +243,7 @@
         containerBounds.set(0, 0, 1200, 2000);
         mToken.onConfigurationChanged(newParentConfig);
         // Assert don't use fixed bounds because the region is enough.
-        assertFalse(mToken.inSizeCompatMode());
+        assertFalse(mToken.hasSizeCompatBounds());
     }
 
     @Test
@@ -325,37 +324,14 @@
     }
 
     @Test
-    public void testReportOrientationChangeOnVisibilityChange() {
+    public void testReportOrientationChange() {
         mToken.setOrientation(SCREEN_ORIENTATION_LANDSCAPE);
 
         mDisplayContent.getDisplayRotation().setFixedToUserRotation(
                 DisplayRotation.FIXED_TO_USER_ROTATION_ENABLED);
 
-        doReturn(Configuration.ORIENTATION_LANDSCAPE).when(mToken.mActivityRecord)
-                .getRequestedConfigurationOrientation();
-
         mTask.mTaskRecord = Mockito.mock(TaskRecord.class, RETURNS_DEEP_STUBS);
-        mToken.commitVisibility(null /* lp */, false /* visible */, TRANSIT_UNSET,
-                true /* performLayout */, false /* isVoiceInteraction */);
-
-        verify(mTask.mTaskRecord).onConfigurationChanged(any(Configuration.class));
-    }
-
-    @Test
-    public void testReportOrientationChangeOnOpeningClosingAppChange() {
-        mToken.setOrientation(SCREEN_ORIENTATION_LANDSCAPE);
-
-        mDisplayContent.getDisplayRotation().setFixedToUserRotation(
-                DisplayRotation.FIXED_TO_USER_ROTATION_ENABLED);
-        mDisplayContent.getDisplayInfo().state = Display.STATE_ON;
-        mDisplayContent.prepareAppTransition(WindowManager.TRANSIT_ACTIVITY_CLOSE,
-                false /* alwaysKeepCurrent */, 0 /* flags */, true /* forceOverride */);
-
-        doReturn(Configuration.ORIENTATION_LANDSCAPE).when(mToken.mActivityRecord)
-                .getRequestedConfigurationOrientation();
-
-        mTask.mTaskRecord = Mockito.mock(TaskRecord.class, RETURNS_DEEP_STUBS);
-        mToken.setVisibility(false /* visible */, false /* deferHidingClient */);
+        mToken.reportDescendantOrientationChangeIfNeeded();
 
         verify(mTask.mTaskRecord).onConfigurationChanged(any(Configuration.class));
     }
@@ -378,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 WindowTestUtils.TestAppWindowToken appToken = createIsolatedTestAppWindowToken();
+            final AppWindowToken appToken = createIsolatedTestAppWindowToken();
 
             appToken.addStartingWindow(mPackageName,
                     android.R.style.Theme, null, "Test", 0, 0, 0, 0, null, true, true, false, true,
@@ -393,8 +369,8 @@
 
     @Test
     public void testTransferStartingWindow() {
-        final WindowTestUtils.TestAppWindowToken token1 = createIsolatedTestAppWindowToken();
-        final WindowTestUtils.TestAppWindowToken token2 = createIsolatedTestAppWindowToken();
+        final AppWindowToken token1 = createIsolatedTestAppWindowToken();
+        final AppWindowToken token2 = createIsolatedTestAppWindowToken();
         token1.addStartingWindow(mPackageName,
                 android.R.style.Theme, null, "Test", 0, 0, 0, 0, null, true, true, false, true,
                 false, false);
@@ -409,8 +385,8 @@
 
     @Test
     public void testTransferStartingWindowWhileCreating() {
-        final WindowTestUtils.TestAppWindowToken token1 = createIsolatedTestAppWindowToken();
-        final WindowTestUtils.TestAppWindowToken token2 = createIsolatedTestAppWindowToken();
+        final AppWindowToken token1 = createIsolatedTestAppWindowToken();
+        final AppWindowToken token2 = createIsolatedTestAppWindowToken();
         ((TestWindowManagerPolicy) token1.mWmService.mPolicy).setRunnableWhenAddingSplashScreen(
                 () -> {
                     // Surprise, ...! Transfer window in the middle of the creation flow.
@@ -427,14 +403,14 @@
         assertHasStartingWindow(token2);
     }
 
-    private WindowTestUtils.TestAppWindowToken createIsolatedTestAppWindowToken() {
+    private AppWindowToken createIsolatedTestAppWindowToken() {
         final TaskStack taskStack = createTaskStackOnDisplay(mDisplayContent);
         final Task task = createTaskInStack(taskStack, 0 /* userId */);
         return createTestAppWindowTokenForGivenTask(task);
     }
 
-    private WindowTestUtils.TestAppWindowToken createTestAppWindowTokenForGivenTask(Task task) {
-        final WindowTestUtils.TestAppWindowToken appToken =
+    private AppWindowToken createTestAppWindowTokenForGivenTask(Task task) {
+        final AppWindowToken appToken =
                 WindowTestUtils.createTestAppWindowToken(mDisplayContent);
         task.addChild(appToken, 0);
         waitUntilHandlersIdle();
@@ -444,8 +420,8 @@
     @Test
     public void testTryTransferStartingWindowFromHiddenAboveToken() {
         // Add two tasks on top of each other.
-        final WindowTestUtils.TestAppWindowToken tokenTop = createIsolatedTestAppWindowToken();
-        final WindowTestUtils.TestAppWindowToken tokenBottom =
+        final AppWindowToken tokenTop = createIsolatedTestAppWindowToken();
+        final AppWindowToken tokenBottom =
                 createTestAppWindowTokenForGivenTask(tokenTop.getTask());
 
         // Add a starting window.
diff --git a/services/tests/wmtests/src/com/android/server/wm/DimmerTests.java b/services/tests/wmtests/src/com/android/server/wm/DimmerTests.java
index a98f79c..73420a0 100644
--- a/services/tests/wmtests/src/com/android/server/wm/DimmerTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/DimmerTests.java
@@ -46,7 +46,7 @@
 
     private static class TestWindowContainer extends WindowContainer<TestWindowContainer> {
         final SurfaceControl mControl = mock(SurfaceControl.class);
-        final SurfaceControl.Transaction mTransaction = mock(SurfaceControl.Transaction.class);
+        final SurfaceControl.Transaction mTransaction = spy(StubTransaction.class);
 
         TestWindowContainer(WindowManagerService wm) {
             super(wm);
@@ -66,7 +66,7 @@
     private static class MockSurfaceBuildingContainer extends WindowContainer<TestWindowContainer> {
         final SurfaceSession mSession = new SurfaceSession();
         final SurfaceControl mHostControl = mock(SurfaceControl.class);
-        final SurfaceControl.Transaction mHostTransaction = mock(SurfaceControl.Transaction.class);
+        final SurfaceControl.Transaction mHostTransaction = spy(StubTransaction.class);
 
         MockSurfaceBuildingContainer(WindowManagerService wm) {
             super(wm);
@@ -118,7 +118,7 @@
     public void setUp() throws Exception {
         mHost = new MockSurfaceBuildingContainer(mWm);
         mSurfaceAnimatorStarter = spy(new SurfaceAnimatorStarterImpl());
-        mTransaction = mock(SurfaceControl.Transaction.class);
+        mTransaction = spy(StubTransaction.class);
         mDimmer = new Dimmer(mHost, mSurfaceAnimatorStarter);
     }
 
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 ae40742..2ba3cbd 100644
--- a/services/tests/wmtests/src/com/android/server/wm/DisplayContentTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/DisplayContentTests.java
@@ -39,6 +39,7 @@
 import static android.view.WindowManager.LayoutParams.TYPE_BASE_APPLICATION;
 import static android.view.WindowManager.LayoutParams.TYPE_STATUS_BAR;
 import static android.view.WindowManager.LayoutParams.TYPE_VOICE_INTERACTION;
+import static android.view.WindowManager.LayoutParams.TYPE_WALLPAPER;
 
 import static com.android.dx.mockito.inline.extended.ExtendedMockito.any;
 import static com.android.dx.mockito.inline.extended.ExtendedMockito.anyBoolean;
@@ -46,6 +47,7 @@
 import static com.android.dx.mockito.inline.extended.ExtendedMockito.doReturn;
 import static com.android.dx.mockito.inline.extended.ExtendedMockito.mock;
 import static com.android.dx.mockito.inline.extended.ExtendedMockito.never;
+import static com.android.dx.mockito.inline.extended.ExtendedMockito.reset;
 import static com.android.dx.mockito.inline.extended.ExtendedMockito.same;
 import static com.android.dx.mockito.inline.extended.ExtendedMockito.spyOn;
 import static com.android.dx.mockito.inline.extended.ExtendedMockito.times;
@@ -239,8 +241,7 @@
         assertEquals(dc, stack.getDisplayContent());
 
         final Task task = createTaskInStack(stack, 0 /* userId */);
-        final WindowTestUtils.TestAppWindowToken token = WindowTestUtils.createTestAppWindowToken(
-                dc);
+        final AppWindowToken token = WindowTestUtils.createTestAppWindowToken(dc);
         task.addChild(token, 0);
         assertEquals(dc, task.getDisplayContent());
         assertEquals(dc, token.getDisplayContent());
@@ -312,7 +313,7 @@
         // Add stack with activity.
         final TaskStack stack0 = createTaskStackOnDisplay(dc0);
         final Task task0 = createTaskInStack(stack0, 0 /* userId */);
-        final WindowTestUtils.TestAppWindowToken token =
+        final AppWindowToken token =
                 WindowTestUtils.createTestAppWindowToken(dc0);
         task0.addChild(token, 0);
         dc0.configureDisplayPolicy();
@@ -320,7 +321,7 @@
 
         final TaskStack stack1 = createTaskStackOnDisplay(dc1);
         final Task task1 = createTaskInStack(stack1, 0 /* userId */);
-        final WindowTestUtils.TestAppWindowToken token1 =
+        final AppWindowToken token1 =
                 WindowTestUtils.createTestAppWindowToken(dc0);
         task1.addChild(token1, 0);
         dc1.configureDisplayPolicy();
@@ -396,6 +397,59 @@
                 mWm.mRoot.getTopFocusedDisplayContent().getDisplayId());
     }
 
+    @Test
+    public void testShouldWaitForSystemDecorWindowsOnBoot_OnDefaultDisplay() {
+        mWm.mSystemBooted = true;
+        final DisplayContent defaultDisplay = mWm.getDefaultDisplayContentLocked();
+        final WindowState[] windows = createNotDrawnWindowsOn(defaultDisplay,
+                TYPE_WALLPAPER, TYPE_APPLICATION);
+
+        // Verify waiting for windows to be drawn.
+        assertTrue(defaultDisplay.shouldWaitForSystemDecorWindowsOnBoot());
+
+        // Verify not waiting for drawn windows.
+        makeWindowsDrawn(windows);
+        assertFalse(defaultDisplay.shouldWaitForSystemDecorWindowsOnBoot());
+    }
+
+    @Test
+    public void testShouldWaitForSystemDecorWindowsOnBoot_OnSecondaryDisplay() {
+        mWm.mSystemBooted = true;
+        final DisplayContent secondaryDisplay = createNewDisplay();
+        final WindowState[] windows = createNotDrawnWindowsOn(secondaryDisplay,
+                TYPE_WALLPAPER, TYPE_APPLICATION);
+
+        // Verify not waiting for display without system decorations.
+        doReturn(false).when(secondaryDisplay).supportsSystemDecorations();
+        assertFalse(secondaryDisplay.shouldWaitForSystemDecorWindowsOnBoot());
+
+        // Verify waiting for non-drawn windows on display with system decorations.
+        reset(secondaryDisplay);
+        doReturn(true).when(secondaryDisplay).supportsSystemDecorations();
+        assertTrue(secondaryDisplay.shouldWaitForSystemDecorWindowsOnBoot());
+
+        // Verify not waiting for drawn windows on display with system decorations.
+        makeWindowsDrawn(windows);
+        assertFalse(secondaryDisplay.shouldWaitForSystemDecorWindowsOnBoot());
+    }
+
+    private WindowState[] createNotDrawnWindowsOn(DisplayContent displayContent, int... types) {
+        final WindowState[] windows = new WindowState[types.length];
+        for (int i = 0; i < types.length; i++) {
+            final int type = types[i];
+            windows[i] = createWindow(null /* parent */, type, displayContent, "window-" + type);
+            windows[i].mHasSurface = false;
+        }
+        return windows;
+    }
+
+    private static void makeWindowsDrawn(WindowState[] windows) {
+        for (WindowState window : windows) {
+            window.mHasSurface = true;
+            window.mWinAnimator.mDrawState = WindowStateAnimator.HAS_DRAWN;
+        }
+    }
+
     /**
      * This tests setting the maximum ui width on a display.
      */
@@ -652,13 +706,13 @@
 
         final ActivityStack stack =
                 new ActivityTestsBase.StackBuilder(mWm.mAtmService.mRootActivityContainer)
-                        .setDisplay(dc.mAcitvityDisplay).build();
+                        .setDisplay(dc.mActivityDisplay).build();
         final ActivityRecord activity = stack.topTask().getTopActivity();
 
         activity.setRequestedOrientation(newOrientation);
 
         final ArgumentCaptor<Configuration> captor = ArgumentCaptor.forClass(Configuration.class);
-        verify(dc.mAcitvityDisplay).updateDisplayOverrideConfigurationLocked(captor.capture(),
+        verify(dc.mActivityDisplay).updateDisplayOverrideConfigurationLocked(captor.capture(),
                 same(activity), anyBoolean(), same(null));
         final Configuration newDisplayConfig = captor.getValue();
         final int expectedOrientation = newOrientation == SCREEN_ORIENTATION_PORTRAIT
@@ -678,12 +732,12 @@
 
         final ActivityStack stack =
                 new ActivityTestsBase.StackBuilder(mWm.mAtmService.mRootActivityContainer)
-                        .setDisplay(dc.mAcitvityDisplay).build();
+                        .setDisplay(dc.mActivityDisplay).build();
         final ActivityRecord activity = stack.topTask().getTopActivity();
 
         activity.setRequestedOrientation(newOrientation);
 
-        verify(dc.mAcitvityDisplay, never()).updateDisplayOverrideConfigurationLocked(any(),
+        verify(dc.mActivityDisplay, never()).updateDisplayOverrideConfigurationLocked(any(),
                 eq(activity), anyBoolean(), same(null));
         assertEquals(dc.getDisplayRotation().getUserRotation(), dc.getRotation());
     }
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 bd17bf2..480c468 100644
--- a/services/tests/wmtests/src/com/android/server/wm/DisplayRotationTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/DisplayRotationTests.java
@@ -68,6 +68,7 @@
 import com.android.server.wm.utils.WmDisplayCutout;
 
 import org.junit.After;
+import org.junit.AfterClass;
 import org.junit.Before;
 import org.junit.BeforeClass;
 import org.junit.Test;
@@ -122,6 +123,12 @@
         sMockWm.mPolicy = mock(WindowManagerPolicy.class);
     }
 
+    @AfterClass
+    public static void tearDownOnce() {
+        // Make sure the fake settings are cleared after the last test method.
+        FakeSettingsProvider.clearSettingsProvider();
+    }
+
     @Before
     public void setUp() {
         FakeSettingsProvider.clearSettingsProvider();
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 9d3c866..304df22 100644
--- a/services/tests/wmtests/src/com/android/server/wm/DragDropControllerTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/DragDropControllerTests.java
@@ -96,7 +96,7 @@
      * Creates a window state which can be used as a drop target.
      */
     private WindowState createDropTargetWindow(String name, int ownerId) {
-        final WindowTestUtils.TestAppWindowToken token = WindowTestUtils.createTestAppWindowToken(
+        final AppWindowToken token = WindowTestUtils.createTestAppWindowToken(
                 mDisplayContent);
         final TaskStack stack = createTaskStackOnDisplay(
                 WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_STANDARD, mDisplayContent);
diff --git a/services/tests/wmtests/src/com/android/server/wm/LaunchParamsControllerTests.java b/services/tests/wmtests/src/com/android/server/wm/LaunchParamsControllerTests.java
index be2ee29..46435eb 100644
--- a/services/tests/wmtests/src/com/android/server/wm/LaunchParamsControllerTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/LaunchParamsControllerTests.java
@@ -422,7 +422,7 @@
 
         @Override
         void saveTask(TaskRecord task) {
-            final int userId = task.userId;
+            final int userId = task.mUserId;
             final ComponentName realActivity = task.realActivity;
             mTmpParams.mPreferredDisplayId = task.getStack().mDisplayId;
             mTmpParams.mWindowingMode = task.getWindowingMode();
@@ -436,7 +436,7 @@
 
         @Override
         void getLaunchParams(TaskRecord task, ActivityRecord activity, LaunchParams params) {
-            final int userId = task != null ? task.userId : activity.mUserId;
+            final int userId = task != null ? task.mUserId : activity.mUserId;
             final ComponentName name = task != null
                     ? task.realActivity : activity.mActivityComponent;
 
diff --git a/services/tests/wmtests/src/com/android/server/wm/LaunchParamsPersisterTests.java b/services/tests/wmtests/src/com/android/server/wm/LaunchParamsPersisterTests.java
index 49d778f..b9fef4b 100644
--- a/services/tests/wmtests/src/com/android/server/wm/LaunchParamsPersisterTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/LaunchParamsPersisterTests.java
@@ -32,7 +32,6 @@
 import static org.mockito.Matchers.any;
 
 import android.content.ComponentName;
-import android.content.pm.PackageList;
 import android.content.pm.PackageManagerInternal;
 import android.graphics.Rect;
 import android.os.UserHandle;
@@ -43,6 +42,7 @@
 import androidx.test.filters.MediumTest;
 
 import com.android.server.LocalServices;
+import com.android.server.pm.PackageList;
 import com.android.server.wm.LaunchParamsController.LaunchParams;
 
 import org.junit.Before;
@@ -115,16 +115,16 @@
                 ACTIVITY_TYPE_STANDARD, /* onTop */ true);
         mTestTask = new TaskBuilder(mSupervisor).setComponent(TEST_COMPONENT).setStack(stack)
                 .build();
-        mTestTask.userId = TEST_USER_ID;
+        mTestTask.mUserId = TEST_USER_ID;
         mTestTask.mLastNonFullscreenBounds = TEST_BOUNDS;
         mTestTask.hasBeenVisible = true;
 
         mTaskWithDifferentComponent = new TaskBuilder(mSupervisor)
                 .setComponent(ALTERNATIVE_COMPONENT).build();
-        mTaskWithDifferentComponent.userId = TEST_USER_ID;
+        mTaskWithDifferentComponent.mUserId = TEST_USER_ID;
 
         mTaskWithDifferentUser = new TaskBuilder(mSupervisor).setComponent(TEST_COMPONENT).build();
-        mTaskWithDifferentUser.userId = ALTERNATIVE_USER_ID;
+        mTaskWithDifferentUser.mUserId = ALTERNATIVE_USER_ID;
 
         mTarget = new LaunchParamsPersister(mPersisterQueue, mSupervisor, mUserFolderGetter);
 
diff --git a/services/tests/wmtests/src/com/android/server/wm/LetterboxTest.java b/services/tests/wmtests/src/com/android/server/wm/LetterboxTest.java
index 2d0416d..15417d7 100644
--- a/services/tests/wmtests/src/com/android/server/wm/LetterboxTest.java
+++ b/services/tests/wmtests/src/com/android/server/wm/LetterboxTest.java
@@ -21,6 +21,7 @@
 import static org.mockito.Mockito.clearInvocations;
 import static org.mockito.Mockito.doAnswer;
 import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.spy;
 import static org.mockito.Mockito.verify;
 import static org.mockito.Mockito.when;
 
@@ -48,8 +49,8 @@
     @Before
     public void setUp() throws Exception {
         mSurfaces = new SurfaceControlMocker();
-        mLetterbox = new Letterbox(mSurfaces, () -> mock(SurfaceControl.Transaction.class));
-        mTransaction = mock(SurfaceControl.Transaction.class);
+        mLetterbox = new Letterbox(mSurfaces, StubTransaction::new);
+        mTransaction = spy(StubTransaction.class);
     }
 
     @Test
diff --git a/services/tests/wmtests/src/com/android/server/wm/LockTaskControllerTest.java b/services/tests/wmtests/src/com/android/server/wm/LockTaskControllerTest.java
index 47c76fc..05e173c 100644
--- a/services/tests/wmtests/src/com/android/server/wm/LockTaskControllerTest.java
+++ b/services/tests/wmtests/src/com/android/server/wm/LockTaskControllerTest.java
@@ -707,7 +707,7 @@
         TaskRecord tr = mock(TaskRecord.class);
         tr.mLockTaskAuth = lockTaskAuth;
         tr.intent = intent;
-        tr.userId = TEST_USER_ID;
+        tr.mUserId = TEST_USER_ID;
         return tr;
     }
 
diff --git a/services/tests/wmtests/src/com/android/server/wm/RecentTasksTest.java b/services/tests/wmtests/src/com/android/server/wm/RecentTasksTest.java
index 94abd34..cc598ff 100644
--- a/services/tests/wmtests/src/com/android/server/wm/RecentTasksTest.java
+++ b/services/tests/wmtests/src/com/android/server/wm/RecentTasksTest.java
@@ -63,7 +63,6 @@
 import android.os.SystemClock;
 import android.platform.test.annotations.Presubmit;
 import android.util.ArraySet;
-import android.util.MutableLong;
 import android.util.SparseBooleanArray;
 
 import androidx.test.filters.MediumTest;
@@ -72,6 +71,7 @@
 
 import org.junit.Before;
 import org.junit.Test;
+import org.junit.runner.RunWith;
 
 import java.io.File;
 import java.util.ArrayList;
@@ -86,6 +86,7 @@
  */
 @MediumTest
 @Presubmit
+@RunWith(WindowTestRunner.class)
 public class RecentTasksTest extends ActivityTestsBase {
     private static final int TEST_USER_0_ID = 0;
     private static final int TEST_USER_1_ID = 10;
@@ -95,10 +96,7 @@
     private static final int INVALID_STACK_ID = 999;
 
     private ActivityDisplay mDisplay;
-    private ActivityDisplay mOtherDisplay;
-    private ActivityDisplay mSingleTaskDisplay;
     private ActivityStack mStack;
-    private ActivityStack mHomeStack;
     private TestTaskPersister mTaskPersister;
     private TestRecentTasks mRecentTasks;
     private TestRunningTasks mRunningTasks;
@@ -111,15 +109,7 @@
     @Before
     public void setUp() throws Exception {
         mTaskPersister = new TestTaskPersister(mContext.getFilesDir());
-
-        // Set testing displays
         mDisplay = mRootActivityContainer.getActivityDisplay(DEFAULT_DISPLAY);
-        mOtherDisplay = createNewActivityDisplay();
-        mSingleTaskDisplay = createNewActivityDisplay();
-        mSingleTaskDisplay.setDisplayToSingleTaskInstance();
-        mRootActivityContainer.addChild(mOtherDisplay, ActivityDisplay.POSITION_TOP);
-        mRootActivityContainer.addChild(mDisplay, ActivityDisplay.POSITION_TOP);
-        mRootActivityContainer.addChild(mSingleTaskDisplay, ActivityDisplay.POSITION_TOP);
 
         // Set the recent tasks we should use for testing in this class.
         mRecentTasks = new TestRecentTasks(mService, mTaskPersister);
@@ -131,8 +121,6 @@
         mRunningTasks = new TestRunningTasks();
         mService.mStackSupervisor.setRunningTasks(mRunningTasks);
 
-        mHomeStack = mDisplay.getOrCreateStack(
-                WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_HOME, true /* onTop */);
         mStack = mDisplay.createStack(
                 WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_STANDARD, true /* onTop */);
         mCallbacksRecorder = new CallbacksRecorder();
@@ -269,7 +257,7 @@
         // other task
         TaskRecord task1 = createTaskBuilder(".Task1")
                 .setFlags(FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_MULTIPLE_TASK)
-                .setStack(mHomeStack).build();
+                .setStack(mDisplay.getHomeStack()).build();
         TaskRecord task2 = createTaskBuilder(".Task1")
                 .setFlags(FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_MULTIPLE_TASK)
                 .setStack(mStack).build();
@@ -446,12 +434,12 @@
         mRecentTasks.add(task3);
         mRecentTasks.add(task4);
 
-        MutableLong prevLastActiveTime = new MutableLong(0);
+        long prevLastActiveTime = 0;
         final ArrayList<TaskRecord> tasks = mRecentTasks.getRawTasks();
         for (int i = 0; i < tasks.size(); i++) {
             final TaskRecord task = tasks.get(i);
-            assertThat(prevLastActiveTime.value).isLessThan(task.lastActiveTime);
-            prevLastActiveTime.value = task.lastActiveTime;
+            assertThat(prevLastActiveTime).isLessThan(task.lastActiveTime);
+            prevLastActiveTime = task.lastActiveTime;
         }
     }
 
@@ -618,7 +606,10 @@
         mRecentTasks.setOnlyTestVisibleRange();
         mRecentTasks.setParameters(-1 /* min */, 3 /* max */, -1 /* ms */);
 
-        ActivityStack singleTaskStack = mSingleTaskDisplay.createStack(
+        final ActivityDisplay singleTaskDisplay =
+                addNewActivityDisplayAt(ActivityDisplay.POSITION_TOP);
+        singleTaskDisplay.setDisplayToSingleTaskInstance();
+        ActivityStack singleTaskStack = singleTaskDisplay.createStack(
                 WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_STANDARD, true /* onTop */);
 
         TaskRecord excludedTask1 = createTaskBuilder(".ExcludedTask1")
@@ -795,7 +786,8 @@
         mRecentTasks.setParameters(-1 /* min */, 1 /* max */, -1 /* ms */);
 
         final ActivityStack homeStack = mDisplay.getHomeStack();
-        final ActivityStack otherDisplayStack = mOtherDisplay.createStack(
+        final ActivityDisplay otherDisplay = addNewActivityDisplayAt(ActivityDisplay.POSITION_TOP);
+        final ActivityStack otherDisplayStack = otherDisplay.createStack(
                 WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_STANDARD, true /* onTop */);
 
         // Add a number of tasks (beyond the max) on each display, ensure that the tasks are not
@@ -890,7 +882,7 @@
     @Test
     public void testNotRestoreRecentTaskApis() {
         final TaskRecord task = createTaskBuilder(".Task").build();
-        final int taskId = task.taskId;
+        final int taskId = task.mTaskId;
         mRecentTasks.add(task);
         // Only keep the task in RecentTasks.
         task.removeWindowContainer();
@@ -976,7 +968,7 @@
                 TEST_USER_0_ID, 0).getList();
         assertTrue(expectedTasks.length == infos.size());
         for (int i = 0; i < infos.size(); i++)  {
-            assertTrue(expectedTasks[i].taskId == infos.get(i).taskId);
+            assertTrue(expectedTasks[i].mTaskId == infos.get(i).taskId);
         }
     }
 
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 5236b5d..f353846 100644
--- a/services/tests/wmtests/src/com/android/server/wm/RecentsAnimationControllerTest.java
+++ b/services/tests/wmtests/src/com/android/server/wm/RecentsAnimationControllerTest.java
@@ -138,14 +138,13 @@
     @Test
     public void testIncludedApps_expectTargetAndVisible() {
         mWm.setRecentsAnimationController(mController);
-        final ActivityStack homeStack = mDisplayContent.mAcitvityDisplay.getOrCreateStack(
+        final ActivityStack homeStack = mDisplayContent.mActivityDisplay.getOrCreateStack(
                 WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_HOME, ON_TOP);
         final AppWindowToken homeAppWindow =
                 new ActivityTestsBase.ActivityBuilder(mWm.mAtmService)
                         .setStack(homeStack)
                         .setCreateTask(true)
-                        .build()
-                        .mAppWindowToken;
+                        .build();
         final AppWindowToken appWindow = createAppWindowToken(mDisplayContent,
                 WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_STANDARD);
         final AppWindowToken hiddenAppWindow = createAppWindowToken(mDisplayContent,
@@ -164,14 +163,13 @@
     @Test
     public void testWallpaperIncluded_expectTarget() throws Exception {
         mWm.setRecentsAnimationController(mController);
-        final ActivityStack homeStack = mDisplayContent.mAcitvityDisplay.getOrCreateStack(
+        final ActivityStack homeStack = mDisplayContent.mActivityDisplay.getOrCreateStack(
                 WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_HOME, ON_TOP);
         final AppWindowToken homeAppWindow =
                 new ActivityTestsBase.ActivityBuilder(mWm.mAtmService)
                         .setStack(homeStack)
                         .setCreateTask(true)
-                        .build()
-                        .mAppWindowToken;
+                        .build();
         final AppWindowToken appWindow = createAppWindowToken(mDisplayContent,
                 WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_STANDARD);
         final WindowState win1 = createWindow(null, TYPE_BASE_APPLICATION, appWindow, "win1");
@@ -194,14 +192,13 @@
     @Test
     public void testWallpaperAnimatorCanceled_expectAnimationKeepsRunning() throws Exception {
         mWm.setRecentsAnimationController(mController);
-        final ActivityStack homeStack = mDisplayContent.mAcitvityDisplay.getOrCreateStack(
+        final ActivityStack homeStack = mDisplayContent.mActivityDisplay.getOrCreateStack(
                 WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_HOME, ON_TOP);
         final AppWindowToken homeAppWindow =
                 new ActivityTestsBase.ActivityBuilder(mWm.mAtmService)
                         .setStack(homeStack)
                         .setCreateTask(true)
-                        .build()
-                        .mAppWindowToken;
+                        .build();
         final AppWindowToken appWindow = createAppWindowToken(mDisplayContent,
                 WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_STANDARD);
         final WindowState win1 = createWindow(null, TYPE_BASE_APPLICATION, appWindow, "win1");
@@ -226,14 +223,13 @@
     @Test
     public void testFinish_expectTargetAndWallpaperAdaptersRemoved() {
         mWm.setRecentsAnimationController(mController);
-        final ActivityStack homeStack = mDisplayContent.mAcitvityDisplay.getOrCreateStack(
+        final ActivityStack homeStack = mDisplayContent.mActivityDisplay.getOrCreateStack(
                 WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_HOME, ON_TOP);
         final AppWindowToken homeAppWindow =
                 new ActivityTestsBase.ActivityBuilder(mWm.mAtmService)
                         .setStack(homeStack)
                         .setCreateTask(true)
-                        .build()
-                        .mAppWindowToken;
+                        .build();
         final WindowState hwin1 = createWindow(null, TYPE_BASE_APPLICATION, homeAppWindow, "hwin1");
         homeAppWindow.addWindow(hwin1);
         final AppWindowToken appWindow = createAppWindowToken(mDisplayContent,
diff --git a/services/tests/wmtests/src/com/android/server/wm/RecentsAnimationTest.java b/services/tests/wmtests/src/com/android/server/wm/RecentsAnimationTest.java
index b4ccd50..ebedde7 100644
--- a/services/tests/wmtests/src/com/android/server/wm/RecentsAnimationTest.java
+++ b/services/tests/wmtests/src/com/android/server/wm/RecentsAnimationTest.java
@@ -97,7 +97,6 @@
                 .setStack(recentsStack)
                 .build();
         ActivityRecord topActivity = new ActivityBuilder(mService).setCreateTask(true).build();
-        topActivity.fullscreen = true;
         topActivity.getActivityStack().moveToFront("testRecentsActivityVisiblility");
 
         doCallRealMethod().when(mRootActivityContainer).ensureActivitiesVisible(
@@ -346,7 +345,7 @@
                 .setCreateTask(true)
                 .setComponent(new ComponentName(mContext.getPackageName(), "Home2"))
                 .build();
-        otherUserHomeActivity.getTaskRecord().userId = TEST_USER_ID;
+        otherUserHomeActivity.getTaskRecord().mUserId = TEST_USER_ID;
 
         ActivityStack fullscreenStack = display.createStack(WINDOWING_MODE_FULLSCREEN,
                 ACTIVITY_TYPE_STANDARD, true /* onTop */);
diff --git a/services/tests/wmtests/src/com/android/server/wm/StubTransaction.java b/services/tests/wmtests/src/com/android/server/wm/StubTransaction.java
index 2ad40f2..f5d08dc 100644
--- a/services/tests/wmtests/src/com/android/server/wm/StubTransaction.java
+++ b/services/tests/wmtests/src/com/android/server/wm/StubTransaction.java
@@ -239,4 +239,15 @@
     public SurfaceControl.Transaction remove(SurfaceControl sc) {
         return this;
     }
+
+    @Override
+    public SurfaceControl.Transaction syncInputWindows() {
+        return this;
+    }
+
+    @Override
+    public SurfaceControl.Transaction setColorSpaceAgnostic(SurfaceControl sc, boolean agnostic) {
+        return this;
+    }
+
 }
diff --git a/services/tests/wmtests/src/com/android/server/wm/TaskLaunchParamsModifierTests.java b/services/tests/wmtests/src/com/android/server/wm/TaskLaunchParamsModifierTests.java
index e6c9b9f..dd85f69 100644
--- a/services/tests/wmtests/src/com/android/server/wm/TaskLaunchParamsModifierTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/TaskLaunchParamsModifierTests.java
@@ -29,6 +29,8 @@
 import static android.util.DisplayMetrics.DENSITY_DEFAULT;
 import static android.view.Display.DEFAULT_DISPLAY;
 
+import static com.android.dx.mockito.inline.extended.ExtendedMockito.doNothing;
+import static com.android.dx.mockito.inline.extended.ExtendedMockito.spyOn;
 import static com.android.server.wm.LaunchParamsController.LaunchParamsModifier.RESULT_CONTINUE;
 import static com.android.server.wm.LaunchParamsController.LaunchParamsModifier.RESULT_SKIP;
 
@@ -65,6 +67,10 @@
 @SmallTest
 @Presubmit
 public class TaskLaunchParamsModifierTests extends ActivityTestsBase {
+    private static final Rect DISPLAY_BOUNDS = new Rect(/* left */ 0, /* top */ 0,
+            /* right */ 1920, /* bottom */ 1080);
+    private static final Rect DISPLAY_STABLE_BOUNDS = new Rect(/* left */ 100,
+            /* top */ 200, /* right */ 1620, /* bottom */ 680);
 
     private ActivityRecord mActivity;
 
@@ -614,7 +620,7 @@
         assertEquals(RESULT_CONTINUE, mTarget.onCalculate(/* task */ null, layout, mActivity,
                 /* source */ null, /* options */ null, mCurrent, mResult));
 
-        assertEquals(0, mResult.mBounds.left);
+        assertEquals(DISPLAY_STABLE_BOUNDS.left, mResult.mBounds.left);
     }
 
     @Test
@@ -630,7 +636,7 @@
         assertEquals(RESULT_CONTINUE, mTarget.onCalculate(/* task */ null, layout, mActivity,
                 /* source */ null, /* options */ null, mCurrent, mResult));
 
-        assertEquals(0, mResult.mBounds.top);
+        assertEquals(DISPLAY_STABLE_BOUNDS.top, mResult.mBounds.top);
     }
 
     @Test
@@ -646,8 +652,8 @@
         assertEquals(RESULT_CONTINUE, mTarget.onCalculate(/* task */ null, layout, mActivity,
                 /* source */ null, /* options */ null, mCurrent, mResult));
 
-        assertEquals(0, mResult.mBounds.left);
-        assertEquals(0, mResult.mBounds.top);
+        assertEquals(DISPLAY_STABLE_BOUNDS.left, mResult.mBounds.left);
+        assertEquals(DISPLAY_STABLE_BOUNDS.top, mResult.mBounds.top);
     }
 
     @Test
@@ -663,7 +669,7 @@
         assertEquals(RESULT_CONTINUE, mTarget.onCalculate(/* task */ null, layout, mActivity,
                 /* source */ null, /* options */ null, mCurrent, mResult));
 
-        assertEquals(1920, mResult.mBounds.right);
+        assertEquals(DISPLAY_STABLE_BOUNDS.right, mResult.mBounds.right);
     }
 
     @Test
@@ -679,7 +685,7 @@
         assertEquals(RESULT_CONTINUE, mTarget.onCalculate(/* task */ null, layout, mActivity,
                 /* source */ null, /* options */ null, mCurrent, mResult));
 
-        assertEquals(1080, mResult.mBounds.bottom);
+        assertEquals(DISPLAY_STABLE_BOUNDS.bottom, mResult.mBounds.bottom);
     }
 
     @Test
@@ -695,8 +701,8 @@
         assertEquals(RESULT_CONTINUE, mTarget.onCalculate(/* task */ null, layout, mActivity,
                 /* source */ null, /* options */ null, mCurrent, mResult));
 
-        assertEquals(1920, mResult.mBounds.right);
-        assertEquals(1080, mResult.mBounds.bottom);
+        assertEquals(DISPLAY_STABLE_BOUNDS.right, mResult.mBounds.right);
+        assertEquals(DISPLAY_STABLE_BOUNDS.bottom, mResult.mBounds.bottom);
     }
 
     @Test
@@ -712,7 +718,7 @@
         assertEquals(RESULT_CONTINUE, mTarget.onCalculate(/* task */ null, layout, mActivity,
                 /* source */ null, /* options */ null, mCurrent, mResult));
 
-        assertEquals(new Rect(900, 500, 1020, 580), mResult.mBounds);
+        assertEquals(new Rect(800, 400, 920, 480), mResult.mBounds);
     }
 
     @Test
@@ -728,7 +734,7 @@
         assertEquals(RESULT_CONTINUE, mTarget.onCalculate(/* task */ null, layout, mActivity,
                 /* source */ null, /* options */ null, mCurrent, mResult));
 
-        assertEquals(new Rect(0, 500, 120, 580), mResult.mBounds);
+        assertEquals(new Rect(100, 400, 220, 480), mResult.mBounds);
     }
 
     @Test
@@ -744,7 +750,7 @@
         assertEquals(RESULT_CONTINUE, mTarget.onCalculate(/* task */ null, layout, mActivity,
                 /* source */ null, /* options */ null, mCurrent, mResult));
 
-        assertEquals(new Rect(900, 0, 1020, 80), mResult.mBounds);
+        assertEquals(new Rect(800, 200, 920, 280), mResult.mBounds);
     }
 
     @Test
@@ -760,7 +766,7 @@
         assertEquals(RESULT_CONTINUE, mTarget.onCalculate(/* task */ null, layout, mActivity,
                 /* source */ null, /* options */ null, mCurrent, mResult));
 
-        assertEquals(new Rect(0, 0, 120, 80), mResult.mBounds);
+        assertEquals(new Rect(100, 200, 220, 280), mResult.mBounds);
     }
 
     @Test
@@ -776,7 +782,7 @@
         assertEquals(RESULT_CONTINUE, mTarget.onCalculate(/* task */ null, layout, mActivity,
                 /* source */ null, /* options */ null, mCurrent, mResult));
 
-        assertEquals(new Rect(1800, 500, 1920, 580), mResult.mBounds);
+        assertEquals(new Rect(1500, 400, 1620, 480), mResult.mBounds);
     }
 
     @Test
@@ -792,7 +798,7 @@
         assertEquals(RESULT_CONTINUE, mTarget.onCalculate(/* task */ null, layout, mActivity,
                 /* source */ null, /* options */ null, mCurrent, mResult));
 
-        assertEquals(new Rect(900, 1000, 1020, 1080), mResult.mBounds);
+        assertEquals(new Rect(800, 600, 920, 680), mResult.mBounds);
     }
 
     @Test
@@ -808,7 +814,7 @@
         assertEquals(RESULT_CONTINUE, mTarget.onCalculate(/* task */ null, layout, mActivity,
                 /* source */ null, /* options */ null, mCurrent, mResult));
 
-        assertEquals(new Rect(1800, 1000, 1920, 1080), mResult.mBounds);
+        assertEquals(new Rect(1500, 600, 1620, 680), mResult.mBounds);
     }
 
     @Test
@@ -819,12 +825,12 @@
         mCurrent.mPreferredDisplayId = freeformDisplay.mDisplayId;
 
         final ActivityInfo.WindowLayout layout = new WindowLayoutBuilder()
-                .setWidthFraction(0.0625f).setHeightFraction(0.1f).build();
+                .setWidthFraction(0.125f).setHeightFraction(0.1f).build();
 
         assertEquals(RESULT_CONTINUE, mTarget.onCalculate(/* task */ null, layout, mActivity,
                 /* source */ null, /* options */ null, mCurrent, mResult));
 
-        assertEquals(new Rect(900, 486, 1020, 594), mResult.mBounds);
+        assertEquals(new Rect(765, 416, 955, 464), mResult.mBounds);
     }
 
     @Test
@@ -952,13 +958,12 @@
         assertEquals(RESULT_CONTINUE, mTarget.onCalculate(/* task */ null, /* layout */ null,
                 mActivity, /* source */ null, options, mCurrent, mResult));
 
-        final Rect displayBounds = freeformDisplay.getBounds();
         assertEquals("Distance to left and right should be equal.",
-                mResult.mBounds.left - displayBounds.left,
-                displayBounds.right - mResult.mBounds.right);
+                mResult.mBounds.left - DISPLAY_STABLE_BOUNDS.left,
+                DISPLAY_STABLE_BOUNDS.right - mResult.mBounds.right, /* delta */ 1);
         assertEquals("Distance to top and bottom should be equal.",
-                mResult.mBounds.top - displayBounds.top,
-                displayBounds.bottom - mResult.mBounds.bottom);
+                mResult.mBounds.top - DISPLAY_STABLE_BOUNDS.top,
+                DISPLAY_STABLE_BOUNDS.bottom - mResult.mBounds.bottom, /* delta */ 1);
     }
 
     @Test
@@ -1041,15 +1046,16 @@
         options.setLaunchDisplayId(freeformDisplay.mDisplayId);
 
         mCurrent.mWindowingMode = WINDOWING_MODE_FREEFORM;
-        mCurrent.mBounds.set(100, 200, 2120, 1380);
+        mCurrent.mBounds.set(100, 300, 1820, 1380);
 
         mActivity.info.applicationInfo.targetSdkVersion = Build.VERSION_CODES.LOLLIPOP;
 
         assertEquals(RESULT_CONTINUE, mTarget.onCalculate(/* task */ null, /* layout */ null,
                 mActivity, /* source */ null, options, mCurrent, mResult));
 
-        assertTrue("Result bounds should start from origin, but it's " + mResult.mBounds,
-                mResult.mBounds.left == 0 && mResult.mBounds.top == 0);
+        assertTrue("Result bounds should start from app bounds's origin, but it's "
+                        + mResult.mBounds,
+                mResult.mBounds.left == 100 && mResult.mBounds.top == 200);
     }
 
     @Test
@@ -1067,15 +1073,16 @@
         options.setLaunchDisplayId(freeformDisplay.mDisplayId);
 
         mCurrent.mWindowingMode = WINDOWING_MODE_FREEFORM;
-        mCurrent.mBounds.set(100, 200, 2120, 1380);
+        mCurrent.mBounds.set(100, 300, 1820, 1380);
 
         mActivity.info.applicationInfo.targetSdkVersion = Build.VERSION_CODES.LOLLIPOP;
 
         assertEquals(RESULT_CONTINUE, mTarget.onCalculate(/* task */ null, /* layout */ null,
                 mActivity, /* source */ null, options, mCurrent, mResult));
 
-        assertTrue("Result bounds should start from origin, but it's " + mResult.mBounds,
-                mResult.mBounds.left == -100 && mResult.mBounds.top == 0);
+        assertTrue("Result bounds should start from top-right corner of app bounds, but "
+                        + "it's " + mResult.mBounds,
+                mResult.mBounds.left == -100 && mResult.mBounds.top == 200);
     }
 
     @Test
@@ -1083,6 +1090,11 @@
         final TestActivityDisplay freeformDisplay = createNewActivityDisplay(
                 WINDOWING_MODE_FREEFORM);
 
+        // This test case requires a relatively big app bounds to ensure the default size calculated
+        // by letterbox won't be too small to hold the minimum width/height.
+        freeformDisplay.mDisplayContent.mDisplayFrames.mStable.set(/* left */ 10, /* top */ 10,
+                /* right */ 1910, /* top */ 1070);
+
         final ActivityOptions options = ActivityOptions.makeBasic();
         options.setLaunchDisplayId(freeformDisplay.mDisplayId);
 
@@ -1245,7 +1257,7 @@
         assertEquals(RESULT_CONTINUE, mTarget.onCalculate(/* task */ null, /* layout */ null,
                 mActivity, /* source */ null, options, mCurrent, mResult));
 
-        assertEquals(new Rect(0, 0, 300, 300), mResult.mBounds);
+        assertEquals(new Rect(100, 200, 400, 500), mResult.mBounds);
     }
 
     @Test
@@ -1301,9 +1313,15 @@
     private TestActivityDisplay createNewActivityDisplay(int windowingMode) {
         final TestActivityDisplay display = addNewActivityDisplayAt(ActivityDisplay.POSITION_TOP);
         display.setWindowingMode(windowingMode);
-        display.setBounds(/* left */ 0, /* top */ 0, /* right */ 1920, /* bottom */ 1080);
+        display.setBounds(DISPLAY_BOUNDS);
         display.getConfiguration().densityDpi = DENSITY_DEFAULT;
         display.getConfiguration().orientation = ORIENTATION_LANDSCAPE;
+        display.mDisplayContent.mDisplayFrames.mStable.set(DISPLAY_STABLE_BOUNDS);
+        spyOn(display.mDisplayContent.mDisplayFrames);
+
+        // We didn't set up the overall environment for this test, so we need to mute the side
+        // effect of layout passes that loosen the stable frame.
+        doNothing().when(display.mDisplayContent.mDisplayFrames).onBeginLayout();
         return display;
     }
 
diff --git a/services/tests/wmtests/src/com/android/server/wm/TaskPositioningControllerTests.java b/services/tests/wmtests/src/com/android/server/wm/TaskPositioningControllerTests.java
index 2ac5f7d..dc89f50 100644
--- a/services/tests/wmtests/src/com/android/server/wm/TaskPositioningControllerTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/TaskPositioningControllerTests.java
@@ -112,7 +112,7 @@
         assertNull(mTarget.getDragWindowHandleLocked());
 
         final DisplayContent content = mock(DisplayContent.class);
-        when(content.findTaskForResizePoint(anyInt(), anyInt())).thenReturn(mWindow.getTask());
+        doReturn(mWindow.getTask()).when(content).findTaskForResizePoint(anyInt(), anyInt());
         assertNotNull(mWindow.getTask().getTopVisibleAppMainWindow());
 
         mTarget.handleTapOutsideTask(content, 0, 0);
diff --git a/services/tests/wmtests/src/com/android/server/wm/TaskRecordTests.java b/services/tests/wmtests/src/com/android/server/wm/TaskRecordTests.java
index d3588a2..0f8fb04 100644
--- a/services/tests/wmtests/src/com/android/server/wm/TaskRecordTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/TaskRecordTests.java
@@ -119,7 +119,7 @@
 
         final byte[] serializedBytes = serializeToBytes(expected);
         final TaskRecord actual = restoreFromBytes(serializedBytes);
-        assertEquals(expected.taskId, actual.taskId);
+        assertEquals(expected.mTaskId, actual.mTaskId);
         assertEquals(expected.mLastNonFullscreenBounds, actual.mLastNonFullscreenBounds);
     }
 
@@ -132,7 +132,7 @@
     @Test
     public void testCopyBaseIntentForTaskInfo() {
         final TaskRecord task = createTaskRecord(1);
-        task.lastTaskDescription = new ActivityManager.TaskDescription();
+        task.mTaskDescription = new ActivityManager.TaskDescription();
         final TaskInfo info = task.getTaskInfo();
 
         // The intent of info should be a copy so assert that they are different instances.
@@ -238,7 +238,7 @@
         ActivityStack stack = new StackBuilder(mRootActivityContainer).setDisplay(display)
                 .setWindowingMode(WINDOWING_MODE_FREEFORM).build();
         TaskRecord task = stack.getChildAt(0);
-        task.getRootActivity().mAppWindowToken.setOrientation(SCREEN_ORIENTATION_UNSPECIFIED);
+        task.getRootActivity().setOrientation(SCREEN_ORIENTATION_UNSPECIFIED);
         DisplayInfo info = new DisplayInfo();
         display.mDisplay.getDisplayInfo(info);
         final Rect fullScreenBounds = new Rect(0, 0, info.logicalWidth, info.logicalHeight);
@@ -648,9 +648,9 @@
         final TaskRecord task1 = getTestTask();
         final ActivityRecord activity1 = task1.getChildAt(0);
 
-        assertEquals(task0.taskId,
+        assertEquals(task0.mTaskId,
                 ActivityRecord.getTaskForActivityLocked(activity0.appToken, false /* onlyRoot */));
-        assertEquals(task1.taskId,
+        assertEquals(task1.mTaskId,
                 ActivityRecord.getTaskForActivityLocked(activity1.appToken,  false /* onlyRoot */));
     }
 
@@ -669,9 +669,9 @@
         // Add one more on top
         final ActivityRecord activity2 = new ActivityBuilder(mService).setTask(task).build();
 
-        assertEquals(task.taskId,
+        assertEquals(task.mTaskId,
                 ActivityRecord.getTaskForActivityLocked(activity0.appToken, true /* onlyRoot */));
-        assertEquals(task.taskId,
+        assertEquals(task.mTaskId,
                 ActivityRecord.getTaskForActivityLocked(activity1.appToken, true /* onlyRoot */));
         assertEquals("No task must be reported for activity that is above root", INVALID_TASK_ID,
                 ActivityRecord.getTaskForActivityLocked(activity2.appToken, true /* onlyRoot */));
@@ -692,9 +692,9 @@
         // Add one more on top
         final ActivityRecord activity2 = new ActivityBuilder(mService).setTask(task).build();
 
-        assertEquals(task.taskId,
+        assertEquals(task.mTaskId,
                 ActivityRecord.getTaskForActivityLocked(activity0.appToken, true /* onlyRoot */));
-        assertEquals(task.taskId,
+        assertEquals(task.mTaskId,
                 ActivityRecord.getTaskForActivityLocked(activity1.appToken, true /* onlyRoot */));
         assertEquals("No task must be reported for activity that is above root", INVALID_TASK_ID,
                 ActivityRecord.getTaskForActivityLocked(activity2.appToken, true /* onlyRoot */));
@@ -718,11 +718,11 @@
         // Add one more activity on top
         final ActivityRecord activity2 = new ActivityBuilder(mService).setTask(task).build();
 
-        assertEquals(task.taskId,
+        assertEquals(task.mTaskId,
                 ActivityRecord.getTaskForActivityLocked(activity0.appToken, false /* onlyRoot */));
-        assertEquals(task.taskId,
+        assertEquals(task.mTaskId,
                 ActivityRecord.getTaskForActivityLocked(activity1.appToken, false /* onlyRoot */));
-        assertEquals(task.taskId,
+        assertEquals(task.mTaskId,
                 ActivityRecord.getTaskForActivityLocked(activity2.appToken, false /* onlyRoot */));
     }
 
@@ -832,8 +832,8 @@
     private TaskRecord createTaskRecord(int taskId) {
         return new TaskRecord(mService, taskId, new Intent(), null, null, null,
                 ActivityBuilder.getDefaultComponent(), null, false, false, false, 0, 10050, null,
-                new ArrayList<>(), 0, false, null, 0, 0, 0, 0, 0, null, 0, false, false, false, 0, 0
-        );
+                new ArrayList<>(), 0, false, null, 0, 0, 0, 0, 0, null, 0, false, false, false, 0,
+                0, null /*ActivityInfo*/, null /*_voiceSession*/, null /*_voiceInteractor*/);
     }
 
     private static class TestTaskRecordFactory extends TaskRecordFactory {
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 5a0f7ed..92ddb35 100644
--- a/services/tests/wmtests/src/com/android/server/wm/TaskStackContainersTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/TaskStackContainersTests.java
@@ -54,7 +54,7 @@
         // Stack should contain visible app window to be considered visible.
         final Task pinnedTask = createTaskInStack(mPinnedStack, 0 /* userId */);
         assertFalse(mPinnedStack.isVisible());
-        final WindowTestUtils.TestAppWindowToken pinnedApp =
+        final AppWindowToken pinnedApp =
                 WindowTestUtils.createTestAppWindowToken(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 87713cb..2eb6ea4 100644
--- a/services/tests/wmtests/src/com/android/server/wm/TaskStackTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/TaskStackTests.java
@@ -68,13 +68,13 @@
     public void testClosingAppDifferentStackOrientation() {
         final TaskStack stack = createTaskStackOnDisplay(mDisplayContent);
         final Task task1 = createTaskInStack(stack, 0 /* userId */);
-        WindowTestUtils.TestAppWindowToken appWindowToken1 =
+        AppWindowToken appWindowToken1 =
                 WindowTestUtils.createTestAppWindowToken(mDisplayContent);
         task1.addChild(appWindowToken1, 0);
         appWindowToken1.setOrientation(SCREEN_ORIENTATION_LANDSCAPE);
 
         final Task task2 = createTaskInStack(stack, 1 /* userId */);
-        WindowTestUtils.TestAppWindowToken appWindowToken2 =
+        AppWindowToken appWindowToken2 =
                 WindowTestUtils.createTestAppWindowToken(mDisplayContent);
         task2.addChild(appWindowToken2, 0);
         appWindowToken2.setOrientation(SCREEN_ORIENTATION_PORTRAIT);
@@ -88,13 +88,13 @@
     public void testMoveTaskToBackDifferentStackOrientation() {
         final TaskStack stack = createTaskStackOnDisplay(mDisplayContent);
         final Task task1 = createTaskInStack(stack, 0 /* userId */);
-        WindowTestUtils.TestAppWindowToken appWindowToken1 =
+        AppWindowToken appWindowToken1 =
                 WindowTestUtils.createTestAppWindowToken(mDisplayContent);
         task1.addChild(appWindowToken1, 0);
         appWindowToken1.setOrientation(SCREEN_ORIENTATION_LANDSCAPE);
 
         final Task task2 = createTaskInStack(stack, 1 /* userId */);
-        WindowTestUtils.TestAppWindowToken appWindowToken2 =
+        AppWindowToken appWindowToken2 =
                 WindowTestUtils.createTestAppWindowToken(mDisplayContent);
         task2.addChild(appWindowToken2, 0);
         appWindowToken2.setOrientation(SCREEN_ORIENTATION_PORTRAIT);
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 16fdf94..f117ff0 100644
--- a/services/tests/wmtests/src/com/android/server/wm/TaskTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/TaskTests.java
@@ -46,7 +46,7 @@
     public void testRemoveContainer() {
         final TaskStack stackController1 = createTaskStackOnDisplay(mDisplayContent);
         final WindowTestUtils.TestTask task = WindowTestUtils.createTestTask(stackController1);
-        final WindowTestUtils.TestAppWindowToken appToken =
+        final AppWindowToken appToken =
                 WindowTestUtils.createAppWindowTokenInTask(mDisplayContent, task);
 
         task.removeIfPossible();
@@ -60,7 +60,7 @@
     public void testRemoveContainer_deferRemoval() {
         final TaskStack stackController1 = createTaskStackOnDisplay(mDisplayContent);
         final WindowTestUtils.TestTask task = WindowTestUtils.createTestTask(stackController1);
-        final WindowTestUtils.TestAppWindowToken appToken =
+        final AppWindowToken appToken =
                 WindowTestUtils.createAppWindowTokenInTask(mDisplayContent, task);
 
         task.mShouldDeferRemoval = true;
diff --git a/services/tests/wmtests/src/com/android/server/wm/TestActivityDisplay.java b/services/tests/wmtests/src/com/android/server/wm/TestActivityDisplay.java
index 778f0ca..9c3ff65 100644
--- a/services/tests/wmtests/src/com/android/server/wm/TestActivityDisplay.java
+++ b/services/tests/wmtests/src/com/android/server/wm/TestActivityDisplay.java
@@ -22,8 +22,11 @@
 
 import static com.android.dx.mockito.inline.extended.ExtendedMockito.anyBoolean;
 import static com.android.dx.mockito.inline.extended.ExtendedMockito.doAnswer;
+import static com.android.dx.mockito.inline.extended.ExtendedMockito.doNothing;
 import static com.android.dx.mockito.inline.extended.ExtendedMockito.spyOn;
 
+import static org.mockito.ArgumentMatchers.any;
+
 import android.hardware.display.DisplayManagerGlobal;
 import android.view.Display;
 import android.view.DisplayInfo;
@@ -85,6 +88,10 @@
             displayRotation.setRotation(rotation);
             return true;
         }).when(displayRotation).updateRotationUnchecked(anyBoolean());
+
+        final InputMonitor inputMonitor = mDisplayContent.getInputMonitor();
+        spyOn(inputMonitor);
+        doNothing().when(inputMonitor).resumeDispatchingLw(any());
     }
 
     @SuppressWarnings("TypeParameterUnusedInFormals")
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 a758681..09e5027 100644
--- a/services/tests/wmtests/src/com/android/server/wm/TestIWindow.java
+++ b/services/tests/wmtests/src/com/android/server/wm/TestIWindow.java
@@ -111,4 +111,8 @@
     @Override
     public void dispatchPointerCaptureChanged(boolean hasCapture) {
     }
+
+    @Override
+    public void showInsets(int types, boolean fromIme) throws RemoteException {
+    }
 }
diff --git a/services/tests/wmtests/src/com/android/server/wm/WindowAnimationSpecTest.java b/services/tests/wmtests/src/com/android/server/wm/WindowAnimationSpecTest.java
index 0330de8..bfc0741 100644
--- a/services/tests/wmtests/src/com/android/server/wm/WindowAnimationSpecTest.java
+++ b/services/tests/wmtests/src/com/android/server/wm/WindowAnimationSpecTest.java
@@ -27,6 +27,7 @@
 import static org.mockito.ArgumentMatchers.argThat;
 import static org.mockito.ArgumentMatchers.eq;
 import static org.mockito.Mockito.never;
+import static org.mockito.Mockito.spy;
 import static org.mockito.Mockito.when;
 
 import android.graphics.Point;
@@ -50,7 +51,7 @@
 @Presubmit
 public class WindowAnimationSpecTest {
     private final SurfaceControl mSurfaceControl = mock(SurfaceControl.class);
-    private final SurfaceControl.Transaction mTransaction = mock(SurfaceControl.Transaction.class);
+    private final SurfaceControl.Transaction mTransaction = spy(StubTransaction.class);
     private final Animation mAnimation = mock(Animation.class);
     private final Rect mStackBounds = new Rect(0, 0, 10, 10);
 
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 0503d74..a09253a 100644
--- a/services/tests/wmtests/src/com/android/server/wm/WindowStateTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/WindowStateTests.java
@@ -330,7 +330,7 @@
         // turn on the screen.
         appWindowToken.setCurrentLaunchCanTurnScreenOn(true);
         first.mAttrs.flags &= ~WindowManager.LayoutParams.FLAG_TURN_SCREEN_ON;
-        doReturn(true).when(appWindowToken.mActivityRecord).canTurnScreenOn();
+        doReturn(true).when(appWindowToken).canTurnScreenOn();
 
         testPrepareWindowToDisplayDuringRelayout(first, true /* expectedWakeupCalled */,
                 false /* expectedCurrentLaunchCanTurnScreenOn */);
@@ -452,7 +452,7 @@
     @Test
     public void testSeamlesslyRotateWindow() {
         final WindowState app = createWindow(null, TYPE_APPLICATION, "app");
-        final SurfaceControl.Transaction t = mock(SurfaceControl.Transaction.class);
+        final SurfaceControl.Transaction t = spy(StubTransaction.class);
 
         app.mHasSurface = true;
         app.mSurfaceControl = mock(SurfaceControl.class);
@@ -536,7 +536,7 @@
 
         final float[] values = new float[9];
         final Matrix matrix = new Matrix();
-        final SurfaceControl.Transaction t = mock(SurfaceControl.Transaction.class);
+        final SurfaceControl.Transaction t = spy(StubTransaction.class);
         final WindowState win1 = createWindow(null, TYPE_APPLICATION, dc, "win1");
         win1.mHasSurface = true;
         win1.mSurfaceControl = mock(SurfaceControl.class);
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 a7a785d..c627c19 100644
--- a/services/tests/wmtests/src/com/android/server/wm/WindowTestUtils.java
+++ b/services/tests/wmtests/src/com/android/server/wm/WindowTestUtils.java
@@ -19,14 +19,17 @@
 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.ComponentName;
-import android.os.Build;
+import android.content.Intent;
+import android.content.pm.ActivityInfo;
 import android.os.IBinder;
-import android.view.IApplicationToken;
+import android.util.Pair;
 import android.view.IWindow;
 import android.view.WindowManager;
 
@@ -48,57 +51,26 @@
     }
 
     /** Creates an {@link AppWindowToken} and adds it to the specified {@link Task}. */
-    static TestAppWindowToken createAppWindowTokenInTask(DisplayContent dc, Task task) {
-        final TestAppWindowToken newToken = createTestAppWindowToken(dc);
+    static AppWindowToken createAppWindowTokenInTask(DisplayContent dc, Task task) {
+        final AppWindowToken newToken = createTestAppWindowToken(dc);
         task.addChild(newToken, POSITION_TOP);
         return newToken;
     }
 
-    static TestAppWindowToken createTestAppWindowToken(DisplayContent dc) {
+    static AppWindowToken createTestAppWindowToken(DisplayContent dc) {
         synchronized (dc.mWmService.mGlobalLock) {
-            return new TestAppWindowToken(dc);
+            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;
         }
     }
 
-    /** Used so we can gain access to some protected members of the {@link AppWindowToken} class. */
-    static class TestAppWindowToken extends AppWindowToken {
-        boolean mOnTop = false;
-
-        private TestAppWindowToken(DisplayContent dc) {
-            super(dc.mWmService, new IApplicationToken.Stub() {
-                @Override
-                public String getName() {
-                    return null;
-                }
-            }, new ComponentName("", ""), false, dc, true /* fillsParent */);
-            mTargetSdk = Build.VERSION_CODES.CUR_DEVELOPMENT;
-            mActivityRecord = mock(ActivityRecord.class);
-            mActivityRecord.app = mock(WindowProcessController.class);
-        }
-
-        int getWindowsCount() {
-            return mChildren.size();
-        }
-
-        boolean hasWindow(WindowState w) {
-            return mChildren.contains(w);
-        }
-
-        WindowState getFirstChild() {
-            return mChildren.peekFirst();
-        }
-
-        WindowState getLastChild() {
-            return mChildren.peekLast();
-        }
-
-        @Override
-        boolean isOnTop() {
-            return mOnTop;
-        }
-
-    }
-
     static TestWindowToken createTestWindowToken(int type, DisplayContent dc) {
         return createTestWindowToken(type, dc, false /* persistOnEmpty */);
     }
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 c574b0f..4c4b21e 100644
--- a/services/tests/wmtests/src/com/android/server/wm/WindowTestsBase.java
+++ b/services/tests/wmtests/src/com/android/server/wm/WindowTestsBase.java
@@ -208,11 +208,11 @@
         return createTestAppWindowToken(dc, windowingMode, activityType);
     }
 
-    WindowTestUtils.TestAppWindowToken createTestAppWindowToken(DisplayContent dc, int
+    AppWindowToken createTestAppWindowToken(DisplayContent dc, int
             windowingMode, int activityType) {
         final TaskStack stack = createTaskStackOnDisplay(windowingMode, activityType, dc);
         final Task task = createTaskInStack(stack, 0 /* userId */);
-        final WindowTestUtils.TestAppWindowToken appWindowToken =
+        final AppWindowToken appWindowToken =
                 WindowTestUtils.createTestAppWindowToken(dc);
         task.addChild(appWindowToken, 0);
         return appWindowToken;
diff --git a/services/usage/java/com/android/server/usage/UsageStatsService.java b/services/usage/java/com/android/server/usage/UsageStatsService.java
index 59d0735..ecee709 100644
--- a/services/usage/java/com/android/server/usage/UsageStatsService.java
+++ b/services/usage/java/com/android/server/usage/UsageStatsService.java
@@ -97,6 +97,8 @@
 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;
@@ -159,7 +161,7 @@
     int mUsageSource;
 
     /** Manages the standby state of apps. */
-    AppStandbyController mAppStandby;
+    AppStandbyInternal mAppStandby;
 
     /** Manages app time limit observers */
     AppTimeLimitController mAppTimeLimit;
@@ -208,7 +210,9 @@
         mPackageManagerInternal = LocalServices.getService(PackageManagerInternal.class);
         mHandler = new H(BackgroundThread.get().getLooper());
 
-        mAppStandby = new AppStandbyController(getContext(), BackgroundThread.get().getLooper());
+        mAppStandby = AppStandbyInternal.newAppStandbyController(
+                UsageStatsService.class.getClassLoader(), getContext(),
+                BackgroundThread.get().getLooper());
 
         mAppTimeLimit = new AppTimeLimitController(
                 new AppTimeLimitController.TimeLimitCallbackListener() {
@@ -1010,7 +1014,7 @@
                         pw.println("Flushed stats to disk");
                         return;
                     } else if ("is-app-standby-enabled".equals(arg)) {
-                        pw.println(mAppStandby.mAppIdleEnabled);
+                        pw.println(mAppStandby.isAppIdleEnabled());
                         return;
                     } else if ("apptimelimit".equals(arg)) {
                         if (i + 1 >= args.length) {
@@ -1729,10 +1733,13 @@
         public void registerAppUsageLimitObserver(int observerId, String[] packages,
                 long timeLimitMs, long timeUsedMs, PendingIntent callbackIntent,
                 String callingPackage) {
+            final int callingUid = Binder.getCallingUid();
+            final DevicePolicyManagerInternal dpmInternal = getDpmInternal();
             if (!hasPermissions(callingPackage,
-                    Manifest.permission.SUSPEND_APPS, Manifest.permission.OBSERVE_APP_USAGE)) {
-                throw new SecurityException("Caller doesn't have both SUSPEND_APPS and "
-                        + "OBSERVE_APP_USAGE permissions");
+                    Manifest.permission.SUSPEND_APPS, Manifest.permission.OBSERVE_APP_USAGE)
+                    && (dpmInternal != null && !dpmInternal.isActiveSupervisionApp(callingUid))) {
+                throw new SecurityException("Caller must be the active supervision app or "
+                        + "it must have both SUSPEND_APPS and OBSERVE_APP_USAGE permissions");
             }
 
             if (packages == null || packages.length == 0) {
@@ -1741,7 +1748,6 @@
             if (callbackIntent == null && timeUsedMs < timeLimitMs) {
                 throw new NullPointerException("callbackIntent can't be null");
             }
-            final int callingUid = Binder.getCallingUid();
             final int userId = UserHandle.getUserId(callingUid);
             final long token = Binder.clearCallingIdentity();
             try {
@@ -1754,13 +1760,15 @@
 
         @Override
         public void unregisterAppUsageLimitObserver(int observerId, String callingPackage) {
+            final int callingUid = Binder.getCallingUid();
+            final DevicePolicyManagerInternal dpmInternal = getDpmInternal();
             if (!hasPermissions(callingPackage,
-                    Manifest.permission.SUSPEND_APPS, Manifest.permission.OBSERVE_APP_USAGE)) {
-                throw new SecurityException("Caller doesn't have both SUSPEND_APPS and "
-                        + "OBSERVE_APP_USAGE permissions");
+                    Manifest.permission.SUSPEND_APPS, Manifest.permission.OBSERVE_APP_USAGE)
+                    && (dpmInternal != null && !dpmInternal.isActiveSupervisionApp(callingUid))) {
+                throw new SecurityException("Caller must be the active supervision app or "
+                        + "it must have both SUSPEND_APPS and OBSERVE_APP_USAGE permissions");
             }
 
-            final int callingUid = Binder.getCallingUid();
             final int userId = UserHandle.getUserId(callingUid);
             final long token = Binder.clearCallingIdentity();
             try {
diff --git a/services/usb/java/com/android/server/usb/UsbHostManager.java b/services/usb/java/com/android/server/usb/UsbHostManager.java
index e899dff..047fcec 100644
--- a/services/usb/java/com/android/server/usb/UsbHostManager.java
+++ b/services/usb/java/com/android/server/usb/UsbHostManager.java
@@ -386,7 +386,7 @@
                 return false;
             }
 
-            UsbDevice.Builder newDeviceBuilder = parser.toAndroidUsbDevice();
+            UsbDevice.Builder newDeviceBuilder = parser.toAndroidUsbDeviceBuilder();
             if (newDeviceBuilder == null) {
                 Slog.e(TAG, "Couldn't create UsbDevice object.");
                 // Tracking
diff --git a/services/usb/java/com/android/server/usb/descriptors/UsbDescriptorParser.java b/services/usb/java/com/android/server/usb/descriptors/UsbDescriptorParser.java
index 6ffbd43..8e7babb 100644
--- a/services/usb/java/com/android/server/usb/descriptors/UsbDescriptorParser.java
+++ b/services/usb/java/com/android/server/usb/descriptors/UsbDescriptorParser.java
@@ -309,17 +309,17 @@
     /**
      * @hide
      */
-    public UsbDevice.Builder toAndroidUsbDevice() {
+    public UsbDevice.Builder toAndroidUsbDeviceBuilder() {
         if (mDeviceDescriptor == null) {
             Log.e(TAG, "toAndroidUsbDevice() ERROR - No Device Descriptor");
             return null;
         }
 
-        UsbDevice.Builder device = mDeviceDescriptor.toAndroid(this);
-        if (device == null) {
+        UsbDevice.Builder builder = mDeviceDescriptor.toAndroid(this);
+        if (builder == null) {
             Log.e(TAG, "toAndroidUsbDevice() ERROR Creating Device");
         }
-        return device;
+        return builder;
     }
 
     /**
@@ -524,6 +524,37 @@
     /**
      * @hide
      */
+    public boolean hasAudioTerminal(int subType) {
+        for (UsbDescriptor descriptor : mDescriptors) {
+            if (descriptor instanceof UsbACInterface) {
+                if (((UsbACInterface) descriptor).getSubclass()
+                        == UsbDescriptor.AUDIO_AUDIOCONTROL
+                        && ((UsbACInterface) descriptor).getSubtype()
+                        == subType) {
+                    return true;
+                }
+            }
+        }
+        return false;
+    }
+
+    /**
+     * @hide
+     */
+    public boolean hasAudioPlayback() {
+        return hasAudioTerminal(UsbACInterface.ACI_OUTPUT_TERMINAL);
+    }
+
+    /**
+     * @hide
+     */
+    public boolean hasAudioCapture() {
+        return hasAudioTerminal(UsbACInterface.ACI_INPUT_TERMINAL);
+    }
+
+    /**
+     * @hide
+     */
     public boolean hasHIDInterface() {
         ArrayList<UsbDescriptor> descriptors =
                 getInterfaceDescriptorsForClass(UsbDescriptor.CLASSID_HID);
diff --git a/services/usb/java/com/android/server/usb/descriptors/UsbDeviceDescriptor.java b/services/usb/java/com/android/server/usb/descriptors/UsbDeviceDescriptor.java
index e6e10fe..9739243 100644
--- a/services/usb/java/com/android/server/usb/descriptors/UsbDeviceDescriptor.java
+++ b/services/usb/java/com/android/server/usb/descriptors/UsbDeviceDescriptor.java
@@ -156,11 +156,11 @@
         for (int index = 0; index < mConfigDescriptors.size(); index++) {
             configs[index] = mConfigDescriptors.get(index).toAndroid(parser);
         }
-        UsbDevice.Builder device = new UsbDevice.Builder(parser.getDeviceAddr(), mVendorID,
-                mProductID, mDevClass, mDevSubClass, mProtocol, mfgName, prodName, versionString,
-                configs, serialStr);
 
-        return device;
+        return new UsbDevice.Builder(parser.getDeviceAddr(), mVendorID,
+                mProductID, mDevClass, mDevSubClass, mProtocol, mfgName, prodName, versionString,
+                configs, serialStr, parser.hasAudioPlayback(), parser.hasAudioCapture(),
+                parser.hasMIDIInterface());
     }
 
     @Override
diff --git a/startop/scripts/app_startup/app_startup_runner.py b/startop/scripts/app_startup/app_startup_runner.py
index fa1c4e6..25ee6f7 100755
--- a/startop/scripts/app_startup/app_startup_runner.py
+++ b/startop/scripts/app_startup/app_startup_runner.py
@@ -233,13 +233,17 @@
                                      simulate: bool,
                                      inodes_path: str,
                                      timeout: int,
-                                     compiler_type: CompilerType) -> DataFrame:
+                                     compiler_type: CompilerType,
+                                     requires_trace_collection: bool) -> DataFrame:
   """ Executes run based on perfetto trace. """
-  passed, perfetto_trace_file = run_perfetto_collector(collector_info,
-                                                       timeout,
-                                                       simulate)
-  if not passed:
-    raise RuntimeError('Cannot run perfetto collector!')
+  if requires_trace_collection:
+    passed, perfetto_trace_file = run_perfetto_collector(collector_info,
+                                                         timeout,
+                                                         simulate)
+    if not passed:
+      raise RuntimeError('Cannot run perfetto collector!')
+  else:
+    perfetto_trace_file = tempfile.NamedTemporaryFile()
 
   with perfetto_trace_file:
     for combos in run_combos:
@@ -271,7 +275,8 @@
     simulate: bool,
     inodes_path: str,
     timeout: int,
-    compiler_type: CompilerType):
+    compiler_type: CompilerType,
+    requires_trace_collection: bool):
   # nothing will work if the screen isn't unlocked first.
   cmd_utils.execute_arbitrary_command([_UNLOCK_SCREEN_SCRIPT],
                                       timeout,
@@ -284,7 +289,8 @@
                                                 simulate,
                                                 inodes_path,
                                                 timeout,
-                                                compiler_type)
+                                                compiler_type,
+                                                requires_trace_collection)
 
 def gather_results(commands: Iterable[Tuple[DataFrame]],
                    key_list: List[str], value_list: List[Tuple[str, ...]]):
@@ -369,11 +375,13 @@
                                                                       CollectorPackageInfo)
 
   print_utils.debug_print_gen("grouped run combinations: ", grouped_combos())
+  requires_trace_collection = any(i in _TRACING_READAHEADS for i in opts.readaheads)
   exec = execute_run_combos(grouped_combos(),
                             opts.simulate,
                             opts.inodes,
                             opts.timeout,
-                            opts.compiler_type)
+                            opts.compiler_type,
+                            requires_trace_collection)
 
   results = gather_results(exec, _COMBINATORIAL_OPTIONS, combos())
 
diff --git a/startop/scripts/iorap/common b/startop/scripts/iorap/common
index 031dabf..387e45d 100755
--- a/startop/scripts/iorap/common
+++ b/startop/scripts/iorap/common
@@ -248,6 +248,6 @@
   local remote_path="$(_iorapd_path_to_data_file "$package" "$activity" "compiled_trace.pb")"
 
   # See 'read_ahead.cc' LOG(INFO).
-  local pattern="ReadAhead completed ($remote_path)"
+  local pattern="Description = $remote_path"
   logcat_wait_for_pattern "$timeout" "$timestamp" "$pattern"
 }
diff --git a/telecomm/java/android/telecom/Conference.java b/telecomm/java/android/telecom/Conference.java
index cd5fd97..d90f46d 100644
--- a/telecomm/java/android/telecom/Conference.java
+++ b/telecomm/java/android/telecom/Conference.java
@@ -24,6 +24,7 @@
 import android.os.Bundle;
 import android.os.SystemClock;
 import android.telecom.Connection.VideoProvider;
+import android.telephony.Annotation.RilRadioTechnology;
 import android.telephony.ServiceState;
 import android.telephony.TelephonyManager;
 import android.util.ArraySet;
@@ -687,7 +688,7 @@
      *
      * @hide
      */
-    public final void setCallRadioTech(@ServiceState.RilRadioTechnology int vrat) {
+    public final void setCallRadioTech(@RilRadioTechnology int vrat) {
         putExtra(TelecomManager.EXTRA_CALL_NETWORK_TYPE,
                 ServiceState.rilRadioTechnologyToNetworkType(vrat));
     }
@@ -700,7 +701,7 @@
      *
      * @hide
      */
-    public final @ServiceState.RilRadioTechnology int getCallRadioTech() {
+    public final @RilRadioTechnology int getCallRadioTech() {
         int voiceNetworkType = TelephonyManager.NETWORK_TYPE_UNKNOWN;
         Bundle extras = getExtras();
         if (extras != null) {
diff --git a/telecomm/java/android/telecom/Connection.java b/telecomm/java/android/telecom/Connection.java
index 0983eea..525b938 100644
--- a/telecomm/java/android/telecom/Connection.java
+++ b/telecomm/java/android/telecom/Connection.java
@@ -34,6 +34,7 @@
 import android.os.ParcelFileDescriptor;
 import android.os.RemoteException;
 import android.os.SystemClock;
+import android.telephony.Annotation.RilRadioTechnology;
 import android.telephony.ServiceState;
 import android.telephony.TelephonyManager;
 import android.util.ArraySet;
@@ -1958,7 +1959,7 @@
      *
      * @hide
      */
-    public final @ServiceState.RilRadioTechnology int getCallRadioTech() {
+    public final @RilRadioTechnology int getCallRadioTech() {
         int voiceNetworkType = TelephonyManager.NETWORK_TYPE_UNKNOWN;
         Bundle extras = getExtras();
         if (extras != null) {
@@ -2409,7 +2410,7 @@
      *
      * @hide
      */
-    public final void setCallRadioTech(@ServiceState.RilRadioTechnology int vrat) {
+    public final void setCallRadioTech(@RilRadioTechnology int vrat) {
         putExtra(TelecomManager.EXTRA_CALL_NETWORK_TYPE,
                 ServiceState.rilRadioTechnologyToNetworkType(vrat));
         // Propagates the call radio technology to its parent {@link android.telecom.Conference}
diff --git a/telephony/common/com/android/internal/telephony/HbpcdLookup.java b/telephony/common/com/android/internal/telephony/HbpcdLookup.java
new file mode 100644
index 0000000..d9a3e72
--- /dev/null
+++ b/telephony/common/com/android/internal/telephony/HbpcdLookup.java
@@ -0,0 +1,124 @@
+/*
+**
+** Copyright 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.internal.telephony;
+
+import android.net.Uri;
+import android.provider.BaseColumns;
+
+/**
+ * @hide
+ */
+public class HbpcdLookup {
+    public static final String AUTHORITY = "hbpcd_lookup";
+
+    public static final Uri CONTENT_URI =
+        Uri.parse("content://" + AUTHORITY);
+
+    public static final String PATH_MCC_IDD = "idd";
+    public static final String PATH_MCC_LOOKUP_TABLE = "lookup";
+    public static final String PATH_MCC_SID_CONFLICT = "conflict";
+    public static final String PATH_MCC_SID_RANGE = "range";
+    public static final String PATH_NANP_AREA_CODE = "nanp";
+    public static final String PATH_ARBITRARY_MCC_SID_MATCH = "arbitrary";
+    public static final String PATH_USERADD_COUNTRY = "useradd";
+
+    public static final String ID = "_id";
+    public static final int IDINDEX = 0;
+
+    /**
+     * @hide
+     */
+    public static class MccIdd implements BaseColumns {
+        public static final Uri CONTENT_URI =
+            Uri.parse("content://" + AUTHORITY + "/" + PATH_MCC_IDD);
+        public static final String DEFAULT_SORT_ORDER = "MCC ASC";
+
+        public static final String MCC = "MCC";
+        public static final String IDD = "IDD";
+
+    }
+
+    /**
+     * @hide
+     */
+    public static class MccLookup implements BaseColumns {
+        public static final Uri CONTENT_URI =
+            Uri.parse("content://" + AUTHORITY + "/" + PATH_MCC_LOOKUP_TABLE);
+        public static final String DEFAULT_SORT_ORDER = "MCC ASC";
+
+        public static final String MCC = "MCC";
+        public static final String COUNTRY_CODE = "Country_Code";
+        public static final String COUNTRY_NAME = "Country_Name";
+        public static final String NDD = "NDD";
+        public static final String NANPS = "NANPS";
+        public static final String GMT_OFFSET_LOW = "GMT_Offset_Low";
+        public static final String GMT_OFFSET_HIGH = "GMT_Offset_High";
+        public static final String GMT_DST_LOW = "GMT_DST_Low";
+        public static final String GMT_DST_HIGH = "GMT_DST_High";
+
+    }
+
+    /**
+     * @hide
+     */
+    public static class MccSidConflicts implements BaseColumns {
+        public static final Uri CONTENT_URI =
+            Uri.parse("content://" + AUTHORITY + "/" + PATH_MCC_SID_CONFLICT);
+        public static final String DEFAULT_SORT_ORDER = "MCC ASC";
+
+        public static final String MCC = "MCC";
+        public static final String SID_CONFLICT = "SID_Conflict";
+
+    }
+
+    /**
+     * @hide
+     */
+    public static class MccSidRange implements BaseColumns {
+        public static final Uri CONTENT_URI =
+            Uri.parse("content://" + AUTHORITY + "/" + PATH_MCC_SID_RANGE);
+        public static final String DEFAULT_SORT_ORDER = "MCC ASC";
+
+        public static final String MCC = "MCC";
+        public static final String RANGE_LOW = "SID_Range_Low";
+        public static final String RANGE_HIGH = "SID_Range_High";
+    }
+
+    /**
+     * @hide
+     */
+    public static class ArbitraryMccSidMatch implements BaseColumns {
+        public static final Uri CONTENT_URI =
+            Uri.parse("content://" + AUTHORITY + "/" + PATH_ARBITRARY_MCC_SID_MATCH);
+        public static final String DEFAULT_SORT_ORDER = "MCC ASC";
+
+        public static final String MCC = "MCC";
+        public static final String SID = "SID";
+
+    }
+
+    /**
+     * @hide
+     */
+    public static class NanpAreaCode implements BaseColumns {
+        public static final Uri CONTENT_URI =
+            Uri.parse("content://" + AUTHORITY + "/" + PATH_NANP_AREA_CODE);
+        public static final String DEFAULT_SORT_ORDER = "Area_Code ASC";
+
+        public static final String AREA_CODE = "Area_Code";
+    }
+}
diff --git a/telephony/common/com/android/internal/telephony/HbpcdUtils.java b/telephony/common/com/android/internal/telephony/HbpcdUtils.java
new file mode 100644
index 0000000..2f31942
--- /dev/null
+++ b/telephony/common/com/android/internal/telephony/HbpcdUtils.java
@@ -0,0 +1,163 @@
+/*
+ * 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.internal.telephony;
+
+import android.content.ContentResolver;
+import android.content.Context;
+import android.database.Cursor;
+import android.telephony.Rlog;
+
+import com.android.internal.telephony.HbpcdLookup.ArbitraryMccSidMatch;
+import com.android.internal.telephony.HbpcdLookup.MccIdd;
+import com.android.internal.telephony.HbpcdLookup.MccLookup;
+import com.android.internal.telephony.HbpcdLookup.MccSidConflicts;
+import com.android.internal.telephony.HbpcdLookup.MccSidRange;
+
+public final class HbpcdUtils {
+    private static final String LOG_TAG = "HbpcdUtils";
+    private static final boolean DBG = false;
+    private ContentResolver resolver = null;
+
+    public HbpcdUtils(Context context) {
+        resolver = context.getContentResolver();
+    }
+
+    /**
+     *  Resolves the unknown MCC with SID and Timezone information.
+    */
+    public int getMcc(int sid, int tz, int DSTflag, boolean isNitzTimeZone) {
+        int tmpMcc = 0;
+
+        // check if SID exists in arbitrary_mcc_sid_match table.
+        // these SIDs are assigned to more than 1 operators, but they are known to
+        // be used by a specific operator, other operators having the same SID are
+        // not using it currently, if that SID is in this table, we don't need to
+        // check other tables.
+        String projection2[] = {ArbitraryMccSidMatch.MCC};
+        Cursor c2 = resolver.query(ArbitraryMccSidMatch.CONTENT_URI, projection2,
+                            ArbitraryMccSidMatch.SID + "=" + sid, null, null);
+
+        if (c2 != null) {
+            int c2Counter = c2.getCount();
+            if (DBG) {
+                Rlog.d(LOG_TAG, "Query unresolved arbitrary table, entries are " + c2Counter);
+            }
+            if (c2Counter == 1) {
+                if (DBG) {
+                    Rlog.d(LOG_TAG, "Query Unresolved arbitrary returned the cursor " + c2);
+                }
+                c2.moveToFirst();
+                tmpMcc = c2.getInt(0);
+                if (DBG) {
+                    Rlog.d(LOG_TAG, "MCC found in arbitrary_mcc_sid_match: " + tmpMcc);
+                }
+                c2.close();
+                return tmpMcc;
+            }
+            c2.close();
+        }
+
+        // Then check if SID exists in mcc_sid_conflict table.
+        // and use the timezone in mcc_lookup table to check which MCC matches.
+        String projection3[] = {MccSidConflicts.MCC};
+        Cursor c3 = resolver.query(MccSidConflicts.CONTENT_URI, projection3,
+                MccSidConflicts.SID_CONFLICT + "=" + sid + " and (((" +
+                MccLookup.GMT_OFFSET_LOW + "<=" + tz + ") and (" + tz + "<=" +
+                MccLookup.GMT_OFFSET_HIGH + ") and (" + "0=" + DSTflag + ")) or ((" +
+                MccLookup.GMT_DST_LOW + "<=" + tz + ") and (" + tz + "<=" +
+                MccLookup.GMT_DST_HIGH + ") and (" + "1=" + DSTflag + ")))",
+                        null, null);
+        if (c3 != null) {
+            int c3Counter = c3.getCount();
+            if (c3Counter > 0) {
+                if (c3Counter > 1) {
+                    Rlog.w(LOG_TAG, "something wrong, get more results for 1 conflict SID: " + c3);
+                }
+                if (DBG) Rlog.d(LOG_TAG, "Query conflict sid returned the cursor " + c3);
+                c3.moveToFirst();
+                tmpMcc = c3.getInt(0);
+                if (DBG) {
+                    Rlog.d(LOG_TAG, "MCC found in mcc_lookup_table. Return tmpMcc = " + tmpMcc);
+                }
+                if (!isNitzTimeZone) {
+                    // time zone is not accurate, it may get wrong mcc, ignore it.
+                    if (DBG) {
+                        Rlog.d(LOG_TAG, "time zone is not accurate, mcc may be " + tmpMcc);
+                    }
+                    tmpMcc = 0;
+                }
+                c3.close();
+                return tmpMcc;
+            } else {
+                c3.close();
+            }
+        }
+
+        // if there is no conflict, then check if SID is in mcc_sid_range.
+        String projection5[] = {MccSidRange.MCC};
+        Cursor c5 = resolver.query(MccSidRange.CONTENT_URI, projection5,
+                MccSidRange.RANGE_LOW + "<=" + sid + " and " +
+                MccSidRange.RANGE_HIGH + ">=" + sid,
+                null, null);
+        if (c5 != null) {
+            if (c5.getCount() > 0) {
+                if (DBG) Rlog.d(LOG_TAG, "Query Range returned the cursor " + c5);
+                c5.moveToFirst();
+                tmpMcc = c5.getInt(0);
+                if (DBG) Rlog.d(LOG_TAG, "SID found in mcc_sid_range. Return tmpMcc = " + tmpMcc);
+                c5.close();
+                return tmpMcc;
+            }
+            c5.close();
+        }
+        if (DBG) Rlog.d(LOG_TAG, "SID NOT found in mcc_sid_range.");
+
+        if (DBG) Rlog.d(LOG_TAG, "Exit getMccByOtherFactors. Return tmpMcc =  " + tmpMcc);
+        // If unknown MCC still could not be resolved,
+        return tmpMcc;
+    }
+
+    /**
+     *  Gets country information with given MCC.
+    */
+    public String getIddByMcc(int mcc) {
+        if (DBG) Rlog.d(LOG_TAG, "Enter getHbpcdInfoByMCC.");
+        String idd = "";
+
+        Cursor c = null;
+
+        String projection[] = {MccIdd.IDD};
+        Cursor cur = resolver.query(MccIdd.CONTENT_URI, projection,
+                MccIdd.MCC + "=" + mcc, null, null);
+        if (cur != null) {
+            if (cur.getCount() > 0) {
+                if (DBG) Rlog.d(LOG_TAG, "Query Idd returned the cursor " + cur);
+                // TODO: for those country having more than 1 IDDs, need more information
+                // to decide which IDD would be used. currently just use the first 1.
+                cur.moveToFirst();
+                idd = cur.getString(0);
+                if (DBG) Rlog.d(LOG_TAG, "IDD = " + idd);
+
+            }
+            cur.close();
+        }
+        if (c != null) c.close();
+
+        if (DBG) Rlog.d(LOG_TAG, "Exit getHbpcdInfoByMCC.");
+        return idd;
+    }
+}
diff --git a/telephony/java/com/android/internal/telephony/SmsApplication.java b/telephony/common/com/android/internal/telephony/SmsApplication.java
similarity index 100%
rename from telephony/java/com/android/internal/telephony/SmsApplication.java
rename to telephony/common/com/android/internal/telephony/SmsApplication.java
diff --git a/telephony/common/com/android/internal/telephony/SmsNumberUtils.java b/telephony/common/com/android/internal/telephony/SmsNumberUtils.java
new file mode 100644
index 0000000..0d33af6
--- /dev/null
+++ b/telephony/common/com/android/internal/telephony/SmsNumberUtils.java
@@ -0,0 +1,627 @@
+/*
+ * 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.internal.telephony;
+
+import android.content.Context;
+import android.database.Cursor;
+import android.database.SQLException;
+import android.os.Binder;
+import android.os.Build;
+import android.os.PersistableBundle;
+import android.telephony.CarrierConfigManager;
+import android.telephony.PhoneNumberUtils;
+import android.telephony.Rlog;
+import android.telephony.TelephonyManager;
+import android.text.TextUtils;
+
+import com.android.internal.telephony.HbpcdLookup.MccIdd;
+import com.android.internal.telephony.HbpcdLookup.MccLookup;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+
+
+/**
+ * This class implements handle the MO SMS target address before sending.
+ * This is special for VZW requirement. Follow the specifications of assisted dialing
+ * of MO SMS while traveling on VZW CDMA, international CDMA or GSM markets.
+ * {@hide}
+ */
+public class SmsNumberUtils {
+    private static final String TAG = "SmsNumberUtils";
+    private static final boolean DBG = Build.IS_DEBUGGABLE;
+
+    private static final String PLUS_SIGN = "+";
+
+    private static final int NANP_SHORT_LENGTH = 7;
+    private static final int NANP_MEDIUM_LENGTH = 10;
+    private static final int NANP_LONG_LENGTH = 11;
+
+    private static final int NANP_CC = 1;
+    private static final String NANP_NDD = "1";
+    private static final String NANP_IDD = "011";
+
+    private static final int MIN_COUNTRY_AREA_LOCAL_LENGTH = 10;
+
+    private static final int GSM_UMTS_NETWORK = 0;
+    private static final int CDMA_HOME_NETWORK = 1;
+    private static final int CDMA_ROAMING_NETWORK = 2;
+
+    private static final int NP_NONE = 0;
+    private static final int NP_NANP_BEGIN = 1;
+
+    /* <Phone Number>, <NXX>-<XXXX> N[2-9] */
+    private static final int NP_NANP_LOCAL = NP_NANP_BEGIN;
+
+    /* <Area_code>-<Phone Number>, <NXX>-<NXX>-<XXXX> N[2-9] */
+    private static final int NP_NANP_AREA_LOCAL = NP_NANP_BEGIN + 1;
+
+    /* <1>-<Area_code>-<Phone Number>, 1-<NXX>-<NXX>-<XXXX> N[2-9] */
+    private static final int NP_NANP_NDD_AREA_LOCAL = NP_NANP_BEGIN + 2;
+
+    /* <+><U.S.Country_code><Area_code><Phone Number>, +1-<NXX>-<NXX>-<XXXX> N[2-9] */
+    private static final int NP_NANP_NBPCD_CC_AREA_LOCAL = NP_NANP_BEGIN + 3;
+
+    /* <Local_IDD><Country_code><Area_code><Phone Number>, 001-1-<NXX>-<NXX>-<XXXX> N[2-9] */
+    private static final int NP_NANP_LOCALIDD_CC_AREA_LOCAL = NP_NANP_BEGIN + 4;
+
+    /* <+><Home_IDD><Country_code><Area_code><Phone Number>, +011-1-<NXX>-<NXX>-<XXXX> N[2-9] */
+    private static final int NP_NANP_NBPCD_HOMEIDD_CC_AREA_LOCAL = NP_NANP_BEGIN + 5;
+
+    private static final int NP_INTERNATIONAL_BEGIN = 100;
+    /* <+>-<Home_IDD>-<Country_code>-<Area_code>-<Phone Number>, +011-86-25-86281234 */
+    private static final int NP_NBPCD_HOMEIDD_CC_AREA_LOCAL = NP_INTERNATIONAL_BEGIN;
+
+    /* <Home_IDD>-<Country_code>-<Area_code>-<Phone Number>, 011-86-25-86281234 */
+    private static final int NP_HOMEIDD_CC_AREA_LOCAL = NP_INTERNATIONAL_BEGIN + 1;
+
+    /* <NBPCD>-<Country_code>-<Area_code>-<Phone Number>, +1-86-25-86281234 */
+    private static final int NP_NBPCD_CC_AREA_LOCAL = NP_INTERNATIONAL_BEGIN + 2;
+
+    /* <Local_IDD>-<Country_code>-<Area_code>-<Phone Number>, 00-86-25-86281234 */
+    private static final int NP_LOCALIDD_CC_AREA_LOCAL = NP_INTERNATIONAL_BEGIN + 3;
+
+    /* <Country_code>-<Area_code>-<Phone Number>, 86-25-86281234*/
+    private static final int NP_CC_AREA_LOCAL = NP_INTERNATIONAL_BEGIN + 4;
+
+    private static int[] ALL_COUNTRY_CODES = null;
+    private static int MAX_COUNTRY_CODES_LENGTH;
+    private static HashMap<String, ArrayList<String>> IDDS_MAPS =
+            new HashMap<String, ArrayList<String>>();
+
+    private static class NumberEntry {
+        public String number;
+        public String IDD;
+        public int countryCode;
+        public NumberEntry(String number) {
+            this.number = number;
+        }
+    }
+
+    /**
+     * Breaks the given number down and formats it according to the rules
+     * for different number plans and different network.
+     *
+     * @param number destination number which need to be format
+     * @param activeMcc current network's mcc
+     * @param networkType current network type
+     *
+     * @return the number after formatting.
+     */
+    private static String formatNumber(Context context, String number,
+                               String activeMcc,
+                               int networkType) {
+        if (number == null ) {
+            throw new IllegalArgumentException("number is null");
+        }
+
+        if (activeMcc == null || activeMcc.trim().length() == 0) {
+            throw new IllegalArgumentException("activeMcc is null or empty!");
+        }
+
+        String networkPortionNumber = PhoneNumberUtils.extractNetworkPortion(number);
+        if (networkPortionNumber == null || networkPortionNumber.length() == 0) {
+            throw new IllegalArgumentException("Number is invalid!");
+        }
+
+        NumberEntry numberEntry = new NumberEntry(networkPortionNumber);
+        ArrayList<String> allIDDs = getAllIDDs(context, activeMcc);
+
+        // First check whether the number is a NANP number.
+        int nanpState = checkNANP(numberEntry, allIDDs);
+        if (DBG) Rlog.d(TAG, "NANP type: " + getNumberPlanType(nanpState));
+
+        if ((nanpState == NP_NANP_LOCAL)
+            || (nanpState == NP_NANP_AREA_LOCAL)
+            || (nanpState == NP_NANP_NDD_AREA_LOCAL)) {
+            return networkPortionNumber;
+        } else if (nanpState == NP_NANP_NBPCD_CC_AREA_LOCAL) {
+            if (networkType == CDMA_HOME_NETWORK
+                    || networkType == CDMA_ROAMING_NETWORK) {
+                // Remove "+"
+                return networkPortionNumber.substring(1);
+            } else {
+                return networkPortionNumber;
+            }
+        } else if (nanpState == NP_NANP_LOCALIDD_CC_AREA_LOCAL) {
+            if (networkType == CDMA_HOME_NETWORK) {
+                return networkPortionNumber;
+            } else if (networkType == GSM_UMTS_NETWORK) {
+                // Remove the local IDD and replace with "+"
+                int iddLength  =  numberEntry.IDD != null ? numberEntry.IDD.length() : 0;
+                return PLUS_SIGN + networkPortionNumber.substring(iddLength);
+            } else if (networkType == CDMA_ROAMING_NETWORK) {
+                // Remove the local IDD
+                int iddLength  =  numberEntry.IDD != null ? numberEntry.IDD.length() : 0;
+                return  networkPortionNumber.substring(iddLength);
+            }
+        }
+
+        int internationalState = checkInternationalNumberPlan(context, numberEntry, allIDDs,
+                NANP_IDD);
+        if (DBG) Rlog.d(TAG, "International type: " + getNumberPlanType(internationalState));
+        String returnNumber = null;
+
+        switch (internationalState) {
+            case NP_NBPCD_HOMEIDD_CC_AREA_LOCAL:
+                if (networkType == GSM_UMTS_NETWORK) {
+                    // Remove "+"
+                    returnNumber = networkPortionNumber.substring(1);
+                }
+                break;
+
+            case NP_NBPCD_CC_AREA_LOCAL:
+                // Replace "+" with "011"
+                returnNumber = NANP_IDD + networkPortionNumber.substring(1);
+                break;
+
+            case NP_LOCALIDD_CC_AREA_LOCAL:
+                if (networkType == GSM_UMTS_NETWORK || networkType == CDMA_ROAMING_NETWORK) {
+                    int iddLength  =  numberEntry.IDD != null ? numberEntry.IDD.length() : 0;
+                    // Replace <Local IDD> to <Home IDD>("011")
+                    returnNumber = NANP_IDD + networkPortionNumber.substring(iddLength);
+                }
+                break;
+
+            case NP_CC_AREA_LOCAL:
+                int countryCode = numberEntry.countryCode;
+
+                if (!inExceptionListForNpCcAreaLocal(numberEntry)
+                    && networkPortionNumber.length() >= 11 && countryCode != NANP_CC) {
+                    // Add "011"
+                    returnNumber = NANP_IDD + networkPortionNumber;
+                }
+                break;
+
+            case NP_HOMEIDD_CC_AREA_LOCAL:
+                returnNumber = networkPortionNumber;
+                break;
+
+            default:
+                // Replace "+" with 011 in CDMA network if the number's country
+                // code is not in the HbpcdLookup database.
+                if (networkPortionNumber.startsWith(PLUS_SIGN)
+                    && (networkType == CDMA_HOME_NETWORK || networkType == CDMA_ROAMING_NETWORK)) {
+                    if (networkPortionNumber.startsWith(PLUS_SIGN + NANP_IDD)) {
+                        // Only remove "+"
+                        returnNumber = networkPortionNumber.substring(1);
+                    } else {
+                        // Replace "+" with "011"
+                        returnNumber = NANP_IDD + networkPortionNumber.substring(1);
+                    }
+                }
+        }
+
+        if (returnNumber == null) {
+            returnNumber = networkPortionNumber;
+        }
+        return returnNumber;
+    }
+
+    /**
+     * Query International direct dialing from HbpcdLookup.db
+     * for specified country code
+     *
+     * @param mcc current network's country code
+     *
+     * @return the IDD array list.
+     */
+    private static ArrayList<String> getAllIDDs(Context context, String mcc) {
+        ArrayList<String> allIDDs = IDDS_MAPS.get(mcc);
+        if (allIDDs != null) {
+            return allIDDs;
+        } else {
+            allIDDs = new ArrayList<String>();
+        }
+
+        String projection[] = {MccIdd.IDD, MccIdd.MCC};
+        String where = null;
+
+        // if mcc is null         : return all rows
+        // if mcc is empty-string : return those rows whose mcc is emptry-string
+        String[] selectionArgs = null;
+        if (mcc != null) {
+            where = MccIdd.MCC + "=?";
+            selectionArgs = new String[] {mcc};
+        }
+
+        Cursor cursor = null;
+        try {
+            cursor = context.getContentResolver().query(MccIdd.CONTENT_URI, projection,
+                    where, selectionArgs, null);
+            if (cursor.getCount() > 0) {
+                while (cursor.moveToNext()) {
+                    String idd = cursor.getString(0);
+                    if (!allIDDs.contains(idd)) {
+                        allIDDs.add(idd);
+                    }
+                }
+            }
+        } catch (SQLException e) {
+            Rlog.e(TAG, "Can't access HbpcdLookup database", e);
+        } finally {
+            if (cursor != null) {
+                cursor.close();
+            }
+        }
+
+        IDDS_MAPS.put(mcc, allIDDs);
+
+        if (DBG) Rlog.d(TAG, "MCC = " + mcc + ", all IDDs = " + allIDDs);
+        return allIDDs;
+    }
+
+
+    /**
+     * Verify if the the destination number is a NANP number
+     *
+     * @param numberEntry including number and IDD array
+     * @param allIDDs the IDD array list of the current network's country code
+     *
+     * @return the number plan type related NANP
+     */
+    private static int checkNANP(NumberEntry numberEntry, ArrayList<String> allIDDs) {
+        boolean isNANP = false;
+        String number = numberEntry.number;
+
+        if (number.length() == NANP_SHORT_LENGTH) {
+            // 7 digits - Seven digit phone numbers
+            char firstChar = number.charAt(0);
+            if (firstChar >= '2' && firstChar <= '9') {
+                isNANP = true;
+                for (int i=1; i< NANP_SHORT_LENGTH; i++ ) {
+                    char c= number.charAt(i);
+                    if (!PhoneNumberUtils.isISODigit(c)) {
+                        isNANP = false;
+                        break;
+                    }
+                }
+            }
+            if (isNANP) {
+                return NP_NANP_LOCAL;
+            }
+        } else if (number.length() == NANP_MEDIUM_LENGTH) {
+            // 10 digits - Three digit area code followed by seven digit phone numbers/
+            if (isNANP(number)) {
+                return NP_NANP_AREA_LOCAL;
+            }
+        } else if (number.length() == NANP_LONG_LENGTH) {
+            // 11 digits - One digit U.S. NDD(National Direct Dial) prefix '1',
+            // followed by three digit area code and seven digit phone numbers
+            if (isNANP(number)) {
+                return NP_NANP_NDD_AREA_LOCAL;
+            }
+        } else if (number.startsWith(PLUS_SIGN)) {
+            number = number.substring(1);
+            if (number.length() == NANP_LONG_LENGTH) {
+                // '+' and 11 digits -'+', followed by NANP CC prefix '1' followed by
+                // three digit area code and seven digit phone numbers
+                if (isNANP(number)) {
+                    return NP_NANP_NBPCD_CC_AREA_LOCAL;
+                }
+            } else if (number.startsWith(NANP_IDD) && number.length() == NANP_LONG_LENGTH + 3) {
+                // '+' and 14 digits -'+', followed by NANP IDD "011" followed by NANP CC
+                // prefix '1' followed by three digit area code and seven digit phone numbers
+                number = number.substring(3);
+                if (isNANP(number)) {
+                    return NP_NANP_NBPCD_HOMEIDD_CC_AREA_LOCAL;
+                }
+            }
+        } else {
+            // Check whether it's NP_NANP_LOCALIDD_CC_AREA_LOCAL
+            for (String idd : allIDDs) {
+                if (number.startsWith(idd)) {
+                    String number2 = number.substring(idd.length());
+                    if(number2 !=null && number2.startsWith(String.valueOf(NANP_CC))){
+                        if (isNANP(number2)) {
+                            numberEntry.IDD = idd;
+                            return NP_NANP_LOCALIDD_CC_AREA_LOCAL;
+                        }
+                    }
+                }
+            }
+        }
+
+        return NP_NONE;
+    }
+
+    private static boolean isNANP(String number) {
+        if (number.length() == NANP_MEDIUM_LENGTH
+            || (number.length() == NANP_LONG_LENGTH  && number.startsWith(NANP_NDD))) {
+            if (number.length() == NANP_LONG_LENGTH) {
+                number = number.substring(1);
+            }
+            return (PhoneNumberUtils.isNanp(number));
+        }
+        return false;
+    }
+
+    /**
+     * Verify if the the destination number is an internal number
+     *
+     * @param numberEntry including number and IDD array
+     * @param allIDDs the IDD array list of the current network's country code
+     *
+     * @return the number plan type related international number
+     */
+    private static int checkInternationalNumberPlan(Context context, NumberEntry numberEntry,
+            ArrayList<String> allIDDs,String homeIDD) {
+        String number = numberEntry.number;
+        int countryCode = -1;
+
+        if (number.startsWith(PLUS_SIGN)) {
+            // +xxxxxxxxxx
+            String numberNoNBPCD = number.substring(1);
+            if (numberNoNBPCD.startsWith(homeIDD)) {
+                // +011xxxxxxxx
+                String numberCountryAreaLocal = numberNoNBPCD.substring(homeIDD.length());
+                if ((countryCode = getCountryCode(context, numberCountryAreaLocal)) > 0) {
+                    numberEntry.countryCode = countryCode;
+                    return NP_NBPCD_HOMEIDD_CC_AREA_LOCAL;
+                }
+            } else if ((countryCode = getCountryCode(context, numberNoNBPCD)) > 0) {
+                numberEntry.countryCode = countryCode;
+                return NP_NBPCD_CC_AREA_LOCAL;
+            }
+
+        } else if (number.startsWith(homeIDD)) {
+            // 011xxxxxxxxx
+            String numberCountryAreaLocal = number.substring(homeIDD.length());
+            if ((countryCode = getCountryCode(context, numberCountryAreaLocal)) > 0) {
+                numberEntry.countryCode = countryCode;
+                return NP_HOMEIDD_CC_AREA_LOCAL;
+            }
+        } else {
+            for (String exitCode : allIDDs) {
+                if (number.startsWith(exitCode)) {
+                    String numberNoIDD = number.substring(exitCode.length());
+                    if ((countryCode = getCountryCode(context, numberNoIDD)) > 0) {
+                        numberEntry.countryCode = countryCode;
+                        numberEntry.IDD = exitCode;
+                        return NP_LOCALIDD_CC_AREA_LOCAL;
+                    }
+                }
+            }
+
+            if (!number.startsWith("0") && (countryCode = getCountryCode(context, number)) > 0) {
+                numberEntry.countryCode = countryCode;
+                return NP_CC_AREA_LOCAL;
+            }
+        }
+        return NP_NONE;
+    }
+
+    /**
+     *  Returns the country code from the given number.
+     */
+    private static int getCountryCode(Context context, String number) {
+        int countryCode = -1;
+        if (number.length() >= MIN_COUNTRY_AREA_LOCAL_LENGTH) {
+            // Check Country code
+            int[] allCCs = getAllCountryCodes(context);
+            if (allCCs == null) {
+                return countryCode;
+            }
+
+            int[] ccArray = new int[MAX_COUNTRY_CODES_LENGTH];
+            for (int i = 0; i < MAX_COUNTRY_CODES_LENGTH; i ++) {
+                ccArray[i] = Integer.parseInt(number.substring(0, i+1));
+            }
+
+            for (int i = 0; i < allCCs.length; i ++) {
+                int tempCC = allCCs[i];
+                for (int j = 0; j < MAX_COUNTRY_CODES_LENGTH; j ++) {
+                    if (tempCC == ccArray[j]) {
+                        if (DBG) Rlog.d(TAG, "Country code = " + tempCC);
+                        return tempCC;
+                    }
+                }
+            }
+        }
+
+        return countryCode;
+    }
+
+    /**
+     *  Gets all country Codes information with given MCC.
+     */
+    private static int[] getAllCountryCodes(Context context) {
+        if (ALL_COUNTRY_CODES != null) {
+            return ALL_COUNTRY_CODES;
+        }
+
+        Cursor cursor = null;
+        try {
+            String projection[] = {MccLookup.COUNTRY_CODE};
+            cursor = context.getContentResolver().query(MccLookup.CONTENT_URI,
+                    projection, null, null, null);
+
+            if (cursor.getCount() > 0) {
+                ALL_COUNTRY_CODES = new int[cursor.getCount()];
+                int i = 0;
+                while (cursor.moveToNext()) {
+                    int countryCode = cursor.getInt(0);
+                    ALL_COUNTRY_CODES[i++] = countryCode;
+                    int length = String.valueOf(countryCode).trim().length();
+                    if (length > MAX_COUNTRY_CODES_LENGTH) {
+                        MAX_COUNTRY_CODES_LENGTH = length;
+                    }
+                }
+            }
+        } catch (SQLException e) {
+            Rlog.e(TAG, "Can't access HbpcdLookup database", e);
+        } finally {
+            if (cursor != null) {
+                cursor.close();
+            }
+        }
+        return ALL_COUNTRY_CODES;
+    }
+
+    private static boolean inExceptionListForNpCcAreaLocal(NumberEntry numberEntry) {
+        int countryCode = numberEntry.countryCode;
+        boolean result = (numberEntry.number.length() == 12
+                          && (countryCode == 7 || countryCode == 20
+                              || countryCode == 65 || countryCode == 90));
+        return result;
+    }
+
+    private static String getNumberPlanType(int state) {
+        String numberPlanType = "Number Plan type (" + state + "): ";
+
+        if (state == NP_NANP_LOCAL) {
+            numberPlanType = "NP_NANP_LOCAL";
+        } else if (state == NP_NANP_AREA_LOCAL) {
+            numberPlanType = "NP_NANP_AREA_LOCAL";
+        } else if (state  == NP_NANP_NDD_AREA_LOCAL) {
+            numberPlanType = "NP_NANP_NDD_AREA_LOCAL";
+        } else if (state == NP_NANP_NBPCD_CC_AREA_LOCAL) {
+            numberPlanType = "NP_NANP_NBPCD_CC_AREA_LOCAL";
+        } else if (state == NP_NANP_LOCALIDD_CC_AREA_LOCAL) {
+            numberPlanType = "NP_NANP_LOCALIDD_CC_AREA_LOCAL";
+        } else if (state == NP_NANP_NBPCD_HOMEIDD_CC_AREA_LOCAL) {
+            numberPlanType = "NP_NANP_NBPCD_HOMEIDD_CC_AREA_LOCAL";
+        } else if (state == NP_NBPCD_HOMEIDD_CC_AREA_LOCAL) {
+            numberPlanType = "NP_NBPCD_HOMEIDD_CC_AREA_LOCAL";
+        } else if (state == NP_HOMEIDD_CC_AREA_LOCAL) {
+            numberPlanType = "NP_HOMEIDD_CC_AREA_LOCAL";
+        } else if (state == NP_NBPCD_CC_AREA_LOCAL) {
+            numberPlanType = "NP_NBPCD_CC_AREA_LOCAL";
+        } else if (state == NP_LOCALIDD_CC_AREA_LOCAL) {
+            numberPlanType = "NP_LOCALIDD_CC_AREA_LOCAL";
+        } else if (state == NP_CC_AREA_LOCAL) {
+            numberPlanType = "NP_CC_AREA_LOCAL";
+        } else {
+            numberPlanType = "Unknown type";
+        }
+        return numberPlanType;
+    }
+
+    /**
+     * Filter the destination number if using VZW sim card.
+     */
+    public static String filterDestAddr(Context context, int subId, String destAddr) {
+        if (DBG) Rlog.d(TAG, "enter filterDestAddr. destAddr=\"" + Rlog.pii(TAG, destAddr) + "\"" );
+
+        if (destAddr == null || !PhoneNumberUtils.isGlobalPhoneNumber(destAddr)) {
+            Rlog.w(TAG, "destAddr" + Rlog.pii(TAG, destAddr) +
+                    " is not a global phone number! Nothing changed.");
+            return destAddr;
+        }
+
+        final TelephonyManager telephonyManager = ((TelephonyManager) context
+                .getSystemService(Context.TELEPHONY_SERVICE)).createForSubscriptionId(subId);
+        final String networkOperator = telephonyManager.getNetworkOperator();
+        String result = null;
+
+        if (needToConvert(context, subId)) {
+            final int networkType = getNetworkType(telephonyManager);
+            if (networkType != -1 && !TextUtils.isEmpty(networkOperator)) {
+                String networkMcc = networkOperator.substring(0, 3);
+                if (networkMcc != null && networkMcc.trim().length() > 0) {
+                    result = formatNumber(context, destAddr, networkMcc, networkType);
+                }
+            }
+        }
+
+        if (DBG) {
+            Rlog.d(TAG, "destAddr is " + ((result != null)?"formatted.":"not formatted."));
+            Rlog.d(TAG, "leave filterDestAddr, new destAddr=\"" + (result != null ? Rlog.pii(TAG,
+                    result) : Rlog.pii(TAG, destAddr)) + "\"");
+        }
+        return result != null ? result : destAddr;
+    }
+
+    /**
+     * Returns the current network type
+     */
+    private static int getNetworkType(TelephonyManager telephonyManager) {
+        int networkType = -1;
+        int phoneType = telephonyManager.getPhoneType();
+
+        if (phoneType == PhoneConstants.PHONE_TYPE_GSM) {
+            networkType = GSM_UMTS_NETWORK;
+        } else if (phoneType == PhoneConstants.PHONE_TYPE_CDMA) {
+            if (isInternationalRoaming(telephonyManager)) {
+                networkType = CDMA_ROAMING_NETWORK;
+            } else {
+                networkType = CDMA_HOME_NETWORK;
+            }
+        } else {
+            if (DBG) Rlog.w(TAG, "warning! unknown mPhoneType value=" + phoneType);
+        }
+
+        return networkType;
+    }
+
+    private static boolean isInternationalRoaming(TelephonyManager telephonyManager) {
+        String operatorIsoCountry = telephonyManager.getNetworkCountryIso();
+        String simIsoCountry = telephonyManager.getSimCountryIso();
+        boolean internationalRoaming = !TextUtils.isEmpty(operatorIsoCountry)
+                && !TextUtils.isEmpty(simIsoCountry)
+                && !simIsoCountry.equals(operatorIsoCountry);
+        if (internationalRoaming) {
+            if ("us".equals(simIsoCountry)) {
+                internationalRoaming = !"vi".equals(operatorIsoCountry);
+            } else if ("vi".equals(simIsoCountry)) {
+                internationalRoaming = !"us".equals(operatorIsoCountry);
+            }
+        }
+        return internationalRoaming;
+    }
+
+    private static boolean needToConvert(Context context, int subId) {
+        // Calling package may not have READ_PHONE_STATE which is required for getConfig().
+        // Clear the calling identity so that it is called as self.
+        final long identity = Binder.clearCallingIdentity();
+        try {
+            CarrierConfigManager configManager = (CarrierConfigManager)
+                    context.getSystemService(Context.CARRIER_CONFIG_SERVICE);
+            if (configManager != null) {
+                PersistableBundle bundle = configManager.getConfigForSubId(subId);
+                if (bundle != null) {
+                    return bundle.getBoolean(CarrierConfigManager
+                            .KEY_SMS_REQUIRES_DESTINATION_NUMBER_CONVERSION_BOOL);
+                }
+            }
+        } finally {
+            Binder.restoreCallingIdentity(identity);
+        }
+        // by default this value is false
+        return false;
+    }
+}
diff --git a/telephony/java/android/provider/Telephony.java b/telephony/java/android/provider/Telephony.java
index 67b252e..bc29b59 100644
--- a/telephony/java/android/provider/Telephony.java
+++ b/telephony/java/android/provider/Telephony.java
@@ -3962,13 +3962,21 @@
         public static final Uri CONTENT_URI = Uri.parse("content://cellbroadcasts");
 
         /**
-         * The id of the subscription which received this cell broadcast message.
+         * The subscription which received this cell broadcast message.
+         * @deprecated use {@link #SLOT_INDEX} instead.
          * <P>Type: INTEGER</P>
          * @hide
          */
         public static final String SUB_ID = "sub_id";
 
         /**
+         * The slot which received this cell broadcast message.
+         * <P>Type: INTEGER</P>
+         * @hide
+         */
+        public static final String SLOT_INDEX = "slot_index";
+
+        /**
          * Message geographical scope. Valid values are:
          * <ul>
          * <li>{@link android.telephony.SmsCbMessage#GEOGRAPHICAL_SCOPE_CELL_WIDE}. meaning the
@@ -4202,7 +4210,7 @@
         public static final String MAXIMUM_WAIT_TIME = "maximum_wait_time";
 
         /**
-         * Query columns for instantiating {@link android.telephony.CellBroadcastMessage} objects.
+         * Query columns for instantiating com.android.cellbroadcastreceiver.CellBroadcastMessage.
          * @hide
          */
         @NonNull
@@ -4235,6 +4243,7 @@
          */
         public static final String[] QUERY_COLUMNS_FWK = {
                 _ID,
+                SLOT_INDEX,
                 GEOGRAPHICAL_SCOPE,
                 PLMN,
                 LAC,
diff --git a/telephony/java/android/telephony/Annotation.java b/telephony/java/android/telephony/Annotation.java
index a884a70..72f758e 100644
--- a/telephony/java/android/telephony/Annotation.java
+++ b/telephony/java/android/telephony/Annotation.java
@@ -469,4 +469,44 @@
     @Retention(RetentionPolicy.SOURCE)
     public @interface DataFailureCause {
     }
+
+    @Retention(RetentionPolicy.SOURCE)
+    @IntDef(prefix = {"PRECISE_CALL_STATE_"},
+            value = {
+            PreciseCallState.PRECISE_CALL_STATE_NOT_VALID,
+            PreciseCallState.PRECISE_CALL_STATE_IDLE,
+            PreciseCallState.PRECISE_CALL_STATE_ACTIVE,
+            PreciseCallState.PRECISE_CALL_STATE_HOLDING,
+            PreciseCallState.PRECISE_CALL_STATE_DIALING,
+            PreciseCallState.PRECISE_CALL_STATE_ALERTING,
+            PreciseCallState. PRECISE_CALL_STATE_INCOMING,
+            PreciseCallState.PRECISE_CALL_STATE_WAITING,
+            PreciseCallState.PRECISE_CALL_STATE_DISCONNECTED,
+            PreciseCallState.PRECISE_CALL_STATE_DISCONNECTING})
+    public @interface PreciseCallStates {}
+
+    @Retention(RetentionPolicy.SOURCE)
+    @IntDef(prefix = {"RIL_RADIO_TECHNOLOGY_" }, value = {
+            ServiceState.RIL_RADIO_TECHNOLOGY_UNKNOWN,
+            ServiceState.RIL_RADIO_TECHNOLOGY_GPRS,
+            ServiceState.RIL_RADIO_TECHNOLOGY_EDGE,
+            ServiceState.RIL_RADIO_TECHNOLOGY_UMTS,
+            ServiceState.RIL_RADIO_TECHNOLOGY_IS95A,
+            ServiceState.RIL_RADIO_TECHNOLOGY_IS95B,
+            ServiceState.RIL_RADIO_TECHNOLOGY_1xRTT,
+            ServiceState.RIL_RADIO_TECHNOLOGY_EVDO_0,
+            ServiceState.RIL_RADIO_TECHNOLOGY_EVDO_A,
+            ServiceState.RIL_RADIO_TECHNOLOGY_HSDPA,
+            ServiceState.RIL_RADIO_TECHNOLOGY_HSUPA,
+            ServiceState.RIL_RADIO_TECHNOLOGY_HSPA,
+            ServiceState.RIL_RADIO_TECHNOLOGY_EVDO_B,
+            ServiceState.RIL_RADIO_TECHNOLOGY_EHRPD,
+            ServiceState.RIL_RADIO_TECHNOLOGY_LTE,
+            ServiceState.RIL_RADIO_TECHNOLOGY_HSPAP,
+            ServiceState.RIL_RADIO_TECHNOLOGY_GSM,
+            ServiceState.RIL_RADIO_TECHNOLOGY_TD_SCDMA,
+            ServiceState.RIL_RADIO_TECHNOLOGY_IWLAN,
+            ServiceState.RIL_RADIO_TECHNOLOGY_LTE_CA,
+            ServiceState.RIL_RADIO_TECHNOLOGY_NR})
+    public @interface RilRadioTechnology {}
 }
diff --git a/telephony/java/android/telephony/CellBroadcastService.java b/telephony/java/android/telephony/CellBroadcastService.java
new file mode 100644
index 0000000..d5e447e
--- /dev/null
+++ b/telephony/java/android/telephony/CellBroadcastService.java
@@ -0,0 +1,112 @@
+/*
+ * 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.telephony;
+
+import android.annotation.CallSuper;
+import android.annotation.SystemApi;
+import android.app.Service;
+import android.content.Intent;
+import android.os.IBinder;
+
+/**
+ * A service which exposes the cell broadcast handling module to the system.
+ * <p>
+ * To extend this class, you must declare the service in your manifest file to require the
+ * {@link android.Manifest.permission#BIND_CELL_BROADCAST_SERVICE} permission and include an intent
+ * filter with the {@link #CELL_BROADCAST_SERVICE_INTERFACE}.
+ * Implementations of this service should run in the phone process and with its UID.
+ * <p>
+ * For example:
+ * <pre>{@code
+ * <manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ *       android:sharedUserId="android.uid.phone">
+ *   <service android:name=".MyCellBroadcastService"
+ *         android:label="@string/service_name"
+ *         android:process="com.android.phone"
+ *         android:exported="true"
+ *         android:permission="android.permission.BIND_CELL_BROADCAST_SERVICE">
+ *     <intent-filter>
+ *           <action android:name="android.telephony.CellBroadcastService" />
+ *     </intent-filter>
+ *   </service>
+ * </manifest>
+ * }</pre>
+ * @hide
+ */
+@SystemApi
+public abstract class CellBroadcastService extends Service {
+
+    public static final String CELL_BROADCAST_SERVICE_INTERFACE =
+            "android.telephony.CellBroadcastService";
+
+    private final ICellBroadcastService.Stub mStubWrapper;
+
+    public CellBroadcastService() {
+        mStubWrapper = new ICellBroadcastServiceWrapper();
+    }
+
+    /**
+     * Handle a GSM cell broadcast SMS message forwarded from the system.
+     * @param slotIndex the index of the slot which received the message
+     * @param message the SMS PDU
+     */
+    public abstract void onGsmCellBroadcastSms(int slotIndex, byte[] message);
+
+    /**
+     * 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
+     */
+    public abstract void onCdmaCellBroadcastSms(int slotIndex, byte[] message);
+
+    /**
+     * If overriding this method, call through to the super method for any unknown actions.
+     * {@inheritDoc}
+     */
+    @Override
+    @CallSuper
+    public IBinder onBind(Intent intent) {
+        return mStubWrapper;
+    }
+
+    /**
+     * A wrapper around ICellBroadcastService that forwards calls to implementations of
+     * {@link CellBroadcastService}.
+     * @hide
+     */
+    public class ICellBroadcastServiceWrapper extends ICellBroadcastService.Stub {
+        /**
+         * Handle a GSM cell broadcast SMS.
+         * @param slotIndex the index of the slot which received the broadcast
+         * @param message the SMS message PDU
+         */
+        @Override
+        public void handleGsmCellBroadcastSms(int slotIndex, byte[] message) {
+            CellBroadcastService.this.onGsmCellBroadcastSms(slotIndex, message);
+        }
+
+        /**
+         * Handle a CDMA cell broadcast SMS.
+         * @param slotIndex the index of the slot which received the broadcast
+         * @param message the SMS message PDU
+         */
+        @Override
+        public void handleCdmaCellBroadcastSms(int slotIndex, byte[] message) {
+            CellBroadcastService.this.onCdmaCellBroadcastSms(slotIndex, message);
+        }
+    }
+}
diff --git a/telephony/java/android/telephony/CellIdentity.java b/telephony/java/android/telephony/CellIdentity.java
index 432978d..b7dab16 100644
--- a/telephony/java/android/telephony/CellIdentity.java
+++ b/telephony/java/android/telephony/CellIdentity.java
@@ -35,6 +35,15 @@
     /** @hide */
     public static final int INVALID_CHANNEL_NUMBER = -1;
 
+    /**
+     * parameters for validation
+     * @hide
+     */
+    public static final int MCC_LENGTH = 3;
+
+    private static final int MNC_MIN_LENGTH = 2;
+    private static final int MNC_MAX_LENGTH = 3;
+
     // Log tag
     /** @hide */
     protected final String mTag;
@@ -207,6 +216,17 @@
         dest.writeString(mAlphaShort);
     }
 
+    /** Used by phone interface manager to verify if a given string is valid MccMnc
+     * @hide
+     */
+    public static boolean isValidPlmn(@NonNull String plmn) {
+        if (plmn.length() < MCC_LENGTH + MNC_MIN_LENGTH
+                || plmn.length() > MCC_LENGTH + MNC_MAX_LENGTH) {
+            return false;
+        }
+        return (isMcc(plmn.substring(0, MCC_LENGTH)) && isMnc(plmn.substring(MCC_LENGTH)));
+    }
+
     /**
      * Construct from Parcel
      * @hide
@@ -267,10 +287,10 @@
     /** @hide */
     private static boolean isMcc(@NonNull String mcc) {
         // ensure no out of bounds indexing
-        if (mcc.length() != 3) return false;
+        if (mcc.length() != MCC_LENGTH) return false;
 
         // Character.isDigit allows all unicode digits, not just [0-9]
-        for (int i = 0; i < 3; i++) {
+        for (int i = 0; i < MCC_LENGTH; i++) {
             if (mcc.charAt(i) < '0' || mcc.charAt(i) > '9') return false;
         }
 
@@ -280,7 +300,7 @@
     /** @hide */
     private static boolean isMnc(@NonNull String mnc) {
         // ensure no out of bounds indexing
-        if (mnc.length() < 2 || mnc.length() > 3) return false;
+        if (mnc.length() < MNC_MIN_LENGTH || mnc.length() > MNC_MAX_LENGTH) return false;
 
         // Character.isDigit allows all unicode digits, not just [0-9]
         for (int i = 0; i < mnc.length(); i++) {
@@ -289,4 +309,5 @@
 
         return true;
     }
+
 }
diff --git a/telephony/java/android/telephony/CellInfoNr.java b/telephony/java/android/telephony/CellInfoNr.java
index 9775abd..cea8323 100644
--- a/telephony/java/android/telephony/CellInfoNr.java
+++ b/telephony/java/android/telephony/CellInfoNr.java
@@ -19,6 +19,8 @@
 import android.annotation.NonNull;
 import android.os.Parcel;
 
+import dalvik.annotation.codegen.CovariantReturnType;
+
 import java.util.Objects;
 
 /**
@@ -46,6 +48,7 @@
     /**
      * @return a {@link CellIdentityNr} instance.
      */
+    @CovariantReturnType(returnType = CellIdentityNr.class, presentAfter = 29)
     @Override
     @NonNull
     public CellIdentity getCellIdentity() {
@@ -55,6 +58,7 @@
     /**
      * @return a {@link CellSignalStrengthNr} instance.
      */
+    @CovariantReturnType(returnType = CellSignalStrengthNr.class, presentAfter = 29)
     @Override
     @NonNull
     public CellSignalStrength getCellSignalStrength() {
diff --git a/telephony/java/android/telephony/ICellBroadcastService.aidl b/telephony/java/android/telephony/ICellBroadcastService.aidl
new file mode 100644
index 0000000..eff64a2
--- /dev/null
+++ b/telephony/java/android/telephony/ICellBroadcastService.aidl
@@ -0,0 +1,32 @@
+/**
+ * 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.telephony;
+
+/**
+ * Service bound to by the system to allow custom handling of cell broadcast messages.
+ * <p>
+ * @see android.telephony.CellBroadcastService
+ * @hide
+ */
+interface ICellBroadcastService {
+
+    /** @see android.telephony.CellBroadcastService#onGsmCellBroadcastSms */
+    oneway void handleGsmCellBroadcastSms(int slotId, in byte[] message);
+
+    /** @see android.telephony.CellBroadcastService#onCdmaCellBroadcastSms */
+    oneway void handleCdmaCellBroadcastSms(int slotId, in byte[] message);
+}
diff --git a/telephony/java/android/telephony/IFinancialSmsCallback.aidl b/telephony/java/android/telephony/IFinancialSmsCallback.aidl
deleted file mode 100644
index aa88615..0000000
--- a/telephony/java/android/telephony/IFinancialSmsCallback.aidl
+++ /dev/null
@@ -1,34 +0,0 @@
-/*
-** Copyright 2019, The Android Open Source Project
-**
-** Licensed under the Apache License, Version 2.0 (the "License");
-** you may not use this file except in compliance with the License.
-** You may obtain a copy of the License at
-**
-**     http://www.apache.org/licenses/LICENSE-2.0
-**
-** Unless required by applicable law or agreed to in writing, software
-** distributed under the License is distributed on an "AS IS" BASIS,
-** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-** See the License for the specific language governing permissions and
-** limitations under the License.
-*/
-package android.telephony;
-
-import android.app.PendingIntent;
-import android.database.CursorWindow;
-import android.net.Uri;
-import android.os.Bundle;
-import com.android.internal.telephony.SmsRawData;
-
-/** Interface for returning back the financial sms messages asynchrously.
- *  @hide
- */
-interface IFinancialSmsCallback {
-    /**
-     * Return sms messages back to calling financial app.
-     *
-     * @param messages the sms messages returned for cinancial app.
-     */
-    oneway void onGetSmsMessagesForFinancialApp(in CursorWindow messages);
-}
diff --git a/telephony/java/android/telephony/ModemActivityInfo.java b/telephony/java/android/telephony/ModemActivityInfo.java
index 43bc85c..d105fe3 100644
--- a/telephony/java/android/telephony/ModemActivityInfo.java
+++ b/telephony/java/android/telephony/ModemActivityInfo.java
@@ -20,11 +20,10 @@
 import android.annotation.SystemApi;
 import android.os.Parcel;
 import android.os.Parcelable;
-
 import android.os.SystemClock;
 import android.util.Range;
+
 import java.util.ArrayList;
-import java.util.Arrays;
 import java.util.List;
 
 /**
@@ -64,17 +63,20 @@
         mTimestamp = timestamp;
         mSleepTimeMs = sleepTimeMs;
         mIdleTimeMs = idleTimeMs;
-        if (txTimeMs != null) {
-            populateTransmitPowerRange(txTimeMs);
-        }
+        populateTransmitPowerRange(txTimeMs);
         mRxTimeMs = rxTimeMs;
     }
 
     /** helper API to populate tx power range for each bucket **/
     private void populateTransmitPowerRange(@NonNull int[] transmitPowerMs) {
-        for (int i = 0; i < Math.min(transmitPowerMs.length, TX_POWER_LEVELS); i++) {
+        int i = 0;
+        for ( ; i < Math.min(transmitPowerMs.length, TX_POWER_LEVELS); i++) {
             mTransmitPowerInfo.add(i, new TransmitPower(TX_POWER_RANGES[i], transmitPowerMs[i]));
         }
+        // Make sure that mTransmitPowerInfo is fully initialized.
+        for ( ; i < TX_POWER_LEVELS; i++) {
+            mTransmitPowerInfo.add(i, new TransmitPower(TX_POWER_RANGES[i], 0));
+        }
     }
 
     @Override
diff --git a/telephony/java/android/telephony/PhoneStateListener.java b/telephony/java/android/telephony/PhoneStateListener.java
index 5734897..1ba0a41 100644
--- a/telephony/java/android/telephony/PhoneStateListener.java
+++ b/telephony/java/android/telephony/PhoneStateListener.java
@@ -184,7 +184,8 @@
     public static final int LISTEN_CELL_INFO = 0x00000400;
 
     /**
-     * Listen for {@link PreciseCallState.State} of ringing, background and foreground calls.
+     * Listen for {@link android.telephony.Annotation.PreciseCallStates} of ringing,
+     * background and foreground calls.
      *
      * @hide
      */
@@ -373,7 +374,7 @@
     @SystemApi
     @TestApi
     @RequiresPermission(Manifest.permission.READ_ACTIVE_EMERGENCY_SESSION)
-    public static final int LISTEN_OUTGOING_CALL_EMERGENCY_NUMBER           = 0x10000000;
+    public static final int LISTEN_OUTGOING_EMERGENCY_CALL                  = 0x10000000;
 
     /**
      * Listen for the emergency number placed from an outgoing SMS.
@@ -386,7 +387,7 @@
     @SystemApi
     @TestApi
     @RequiresPermission(Manifest.permission.READ_ACTIVE_EMERGENCY_SESSION)
-    public static final int LISTEN_OUTGOING_SMS_EMERGENCY_NUMBER            = 0x20000000;
+    public static final int LISTEN_OUTGOING_EMERGENCY_SMS                   = 0x20000000;
 
     /*
      * Subscription used to listen to the phone state changes
@@ -877,6 +878,7 @@
      * @hide
      */
     @SystemApi
+    @TestApi
     public void onOutgoingEmergencyCall(@NonNull EmergencyNumber placedEmergencyNumber) {
         // default implementation empty
     }
@@ -888,6 +890,7 @@
      * @hide
      */
     @SystemApi
+    @TestApi
     public void onOutgoingEmergencySms(@NonNull EmergencyNumber sentEmergencyNumber) {
         // default implementation empty
     }
diff --git a/telephony/java/android/telephony/PreciseCallState.java b/telephony/java/android/telephony/PreciseCallState.java
index f929649..9f75332 100644
--- a/telephony/java/android/telephony/PreciseCallState.java
+++ b/telephony/java/android/telephony/PreciseCallState.java
@@ -23,6 +23,7 @@
 import android.annotation.UnsupportedAppUsage;
 import android.os.Parcel;
 import android.os.Parcelable;
+import android.telephony.Annotation.PreciseCallStates;
 import android.telephony.DisconnectCause;
 import android.telephony.PreciseDisconnectCause;
 
@@ -48,22 +49,6 @@
 @SystemApi
 public final class PreciseCallState implements Parcelable {
 
-    /** @hide */
-    @Retention(RetentionPolicy.SOURCE)
-    @IntDef(prefix = {"PRECISE_CALL_STATE_"},
-            value = {
-                    PRECISE_CALL_STATE_NOT_VALID,
-                    PRECISE_CALL_STATE_IDLE,
-                    PRECISE_CALL_STATE_ACTIVE,
-                    PRECISE_CALL_STATE_HOLDING,
-                    PRECISE_CALL_STATE_DIALING,
-                    PRECISE_CALL_STATE_ALERTING,
-                    PRECISE_CALL_STATE_INCOMING,
-                    PRECISE_CALL_STATE_WAITING,
-                    PRECISE_CALL_STATE_DISCONNECTED,
-                    PRECISE_CALL_STATE_DISCONNECTING})
-    public @interface State {}
-
     /** Call state is not valid (Not received a call state). */
     public static final int PRECISE_CALL_STATE_NOT_VALID =      -1;
     /** Call state: No activity. */
@@ -85,9 +70,9 @@
     /** Call state: Disconnecting. */
     public static final int PRECISE_CALL_STATE_DISCONNECTING =  8;
 
-    private @State int mRingingCallState = PRECISE_CALL_STATE_NOT_VALID;
-    private @State int mForegroundCallState = PRECISE_CALL_STATE_NOT_VALID;
-    private @State int mBackgroundCallState = PRECISE_CALL_STATE_NOT_VALID;
+    private @PreciseCallStates int mRingingCallState = PRECISE_CALL_STATE_NOT_VALID;
+    private @PreciseCallStates int mForegroundCallState = PRECISE_CALL_STATE_NOT_VALID;
+    private @PreciseCallStates int mBackgroundCallState = PRECISE_CALL_STATE_NOT_VALID;
     private int mDisconnectCause = DisconnectCause.NOT_VALID;
     private int mPreciseDisconnectCause = PreciseDisconnectCause.NOT_VALID;
 
@@ -97,8 +82,9 @@
      * @hide
      */
     @UnsupportedAppUsage
-    public PreciseCallState(@State int ringingCall, @State int foregroundCall,
-                            @State int backgroundCall, int disconnectCause,
+    public PreciseCallState(@PreciseCallStates int ringingCall,
+                            @PreciseCallStates int foregroundCall,
+                            @PreciseCallStates int backgroundCall, int disconnectCause,
                             int preciseDisconnectCause) {
         mRingingCallState = ringingCall;
         mForegroundCallState = foregroundCall;
@@ -131,21 +117,21 @@
     /**
      * Returns the precise ringing call state.
      */
-    public @State int getRingingCallState() {
+    public @PreciseCallStates int getRingingCallState() {
         return mRingingCallState;
     }
 
     /**
      * Returns the precise foreground call state.
      */
-    public @State int getForegroundCallState() {
+    public @PreciseCallStates int getForegroundCallState() {
         return mForegroundCallState;
     }
 
     /**
      * Returns the precise background call state.
      */
-    public @State int getBackgroundCallState() {
+    public @PreciseCallStates int getBackgroundCallState() {
         return mBackgroundCallState;
     }
 
diff --git a/telephony/java/android/telephony/ServiceState.java b/telephony/java/android/telephony/ServiceState.java
index c575129..1d00b4f 100644
--- a/telephony/java/android/telephony/ServiceState.java
+++ b/telephony/java/android/telephony/ServiceState.java
@@ -30,6 +30,7 @@
 import android.telephony.AccessNetworkConstants.AccessNetworkType;
 import android.telephony.AccessNetworkConstants.TransportType;
 import android.telephony.Annotation.NetworkType;
+import android.telephony.Annotation.RilRadioTechnology;
 import android.telephony.NetworkRegistrationInfo.Domain;
 import android.telephony.NetworkRegistrationInfo.NRState;
 import android.text.TextUtils;
@@ -155,32 +156,6 @@
      */
     public static final int DUPLEX_MODE_TDD = 2;
 
-    /** @hide */
-    @Retention(RetentionPolicy.SOURCE)
-    @IntDef(prefix = { "RIL_RADIO_TECHNOLOGY_" },
-            value = {
-                    RIL_RADIO_TECHNOLOGY_UNKNOWN,
-                    RIL_RADIO_TECHNOLOGY_GPRS,
-                    RIL_RADIO_TECHNOLOGY_EDGE,
-                    RIL_RADIO_TECHNOLOGY_UMTS,
-                    RIL_RADIO_TECHNOLOGY_IS95A,
-                    RIL_RADIO_TECHNOLOGY_IS95B,
-                    RIL_RADIO_TECHNOLOGY_1xRTT,
-                    RIL_RADIO_TECHNOLOGY_EVDO_0,
-                    RIL_RADIO_TECHNOLOGY_EVDO_A,
-                    RIL_RADIO_TECHNOLOGY_HSDPA,
-                    RIL_RADIO_TECHNOLOGY_HSUPA,
-                    RIL_RADIO_TECHNOLOGY_HSPA,
-                    RIL_RADIO_TECHNOLOGY_EVDO_B,
-                    RIL_RADIO_TECHNOLOGY_EHRPD,
-                    RIL_RADIO_TECHNOLOGY_LTE,
-                    RIL_RADIO_TECHNOLOGY_HSPAP,
-                    RIL_RADIO_TECHNOLOGY_GSM,
-                    RIL_RADIO_TECHNOLOGY_TD_SCDMA,
-                    RIL_RADIO_TECHNOLOGY_IWLAN,
-                    RIL_RADIO_TECHNOLOGY_LTE_CA,
-                    RIL_RADIO_TECHNOLOGY_NR})
-    public @interface RilRadioTechnology {}
     /**
      * Available radio technologies for GSM, UMTS and CDMA.
      * Duplicates the constants from hardware/radio/include/ril.h
@@ -988,6 +963,9 @@
             case RIL_RADIO_TECHNOLOGY_LTE_CA:
                 rtString = "LTE_CA";
                 break;
+            case RIL_RADIO_TECHNOLOGY_NR:
+                rtString = "LTE_NR";
+                break;
             default:
                 rtString = "Unexpected";
                 Rlog.w(LOG_TAG, "Unexpected radioTechnology=" + rt);
@@ -1554,6 +1532,7 @@
                 return AccessNetworkType.CDMA2000;
             case RIL_RADIO_TECHNOLOGY_LTE:
             case RIL_RADIO_TECHNOLOGY_LTE_CA:
+            case RIL_RADIO_TECHNOLOGY_NR:
                 return AccessNetworkType.EUTRAN;
             case RIL_RADIO_TECHNOLOGY_IWLAN:
                 return AccessNetworkType.IWLAN;
@@ -1602,6 +1581,8 @@
                 return ServiceState.RIL_RADIO_TECHNOLOGY_IWLAN;
             case TelephonyManager.NETWORK_TYPE_LTE_CA:
                 return ServiceState.RIL_RADIO_TECHNOLOGY_LTE_CA;
+            case TelephonyManager.NETWORK_TYPE_NR:
+                return ServiceState.RIL_RADIO_TECHNOLOGY_NR;
             default:
                 return ServiceState.RIL_RADIO_TECHNOLOGY_UNKNOWN;
         }
@@ -1692,7 +1673,8 @@
                 || radioTechnology == RIL_RADIO_TECHNOLOGY_GSM
                 || radioTechnology == RIL_RADIO_TECHNOLOGY_TD_SCDMA
                 || radioTechnology == RIL_RADIO_TECHNOLOGY_IWLAN
-                || radioTechnology == RIL_RADIO_TECHNOLOGY_LTE_CA;
+                || radioTechnology == RIL_RADIO_TECHNOLOGY_LTE_CA
+                || radioTechnology == RIL_RADIO_TECHNOLOGY_NR;
 
     }
 
diff --git a/telephony/java/android/telephony/SmsCbMessage.java b/telephony/java/android/telephony/SmsCbMessage.java
index c078764..dc991b9 100644
--- a/telephony/java/android/telephony/SmsCbMessage.java
+++ b/telephony/java/android/telephony/SmsCbMessage.java
@@ -207,17 +207,19 @@
     /** CMAS warning area coordinates. */
     private final List<Geometry> mGeometries;
 
+    private int mSlotIndex = 0;
+
     /**
      * Create a new SmsCbMessage with the specified data.
      */
     public SmsCbMessage(int messageFormat, int geographicalScope, int serialNumber,
             @NonNull SmsCbLocation location, int serviceCategory, @Nullable String language,
             @Nullable String body, int priority, @Nullable SmsCbEtwsInfo etwsWarningInfo,
-            @Nullable SmsCbCmasInfo cmasWarningInfo) {
+            @Nullable SmsCbCmasInfo cmasWarningInfo, int slotIndex) {
 
         this(messageFormat, geographicalScope, serialNumber, location, serviceCategory, language,
                 body, priority, etwsWarningInfo, cmasWarningInfo, 0 /* maximumWaitingTime */,
-                null /* geometries */, System.currentTimeMillis());
+                null /* geometries */, System.currentTimeMillis(), slotIndex);
     }
 
     /**
@@ -227,7 +229,8 @@
     public SmsCbMessage(int messageFormat, int geographicalScope, int serialNumber,
             SmsCbLocation location, int serviceCategory, String language, String body,
             int priority, SmsCbEtwsInfo etwsWarningInfo, SmsCbCmasInfo cmasWarningInfo,
-            int maximumWaitTimeSec, List<Geometry> geometries, long receivedTimeMillis) {
+            int maximumWaitTimeSec, List<Geometry> geometries, long receivedTimeMillis,
+            int slotIndex) {
         mMessageFormat = messageFormat;
         mGeographicalScope = geographicalScope;
         mSerialNumber = serialNumber;
@@ -241,6 +244,7 @@
         mReceivedTimeMillis = receivedTimeMillis;
         mGeometries = geometries;
         mMaximumWaitTimeSec = maximumWaitTimeSec;
+        mSlotIndex = slotIndex;
     }
 
     /**
@@ -278,6 +282,7 @@
         String geoStr = in.readString();
         mGeometries = geoStr != null ? CbGeoUtils.parseGeometriesFromString(geoStr) : null;
         mMaximumWaitTimeSec = in.readInt();
+        mSlotIndex = in.readInt();
     }
 
     /**
@@ -312,6 +317,7 @@
         dest.writeString(
                 mGeometries != null ? CbGeoUtils.encodeGeometriesToString(mGeometries) : null);
         dest.writeInt(mMaximumWaitTimeSec);
+        dest.writeInt(mSlotIndex);
     }
 
     @NonNull
@@ -423,6 +429,14 @@
     }
 
     /**
+     * Get the slotIndex associated with this message.
+     * @return the slotIndex associated with this message
+     */
+    public int getSlotIndex() {
+        return mSlotIndex;
+    }
+
+    /**
      * Get the message format ({@link #MESSAGE_FORMAT_3GPP} or {@link #MESSAGE_FORMAT_3GPP2}).
      * @return an integer representing 3GPP or 3GPP2 message format
      */
@@ -502,6 +516,7 @@
                 + (mEtwsWarningInfo != null ? (", " + mEtwsWarningInfo.toString()) : "")
                 + (mCmasWarningInfo != null ? (", " + mCmasWarningInfo.toString()) : "")
                 + ", maximumWaitingTime = " + mMaximumWaitTimeSec
+                + ", slotIndex = " + mSlotIndex
                 + ", geo=" + (mGeometries != null
                 ? CbGeoUtils.encodeGeometriesToString(mGeometries) : "null")
                 + '}';
@@ -522,6 +537,7 @@
     @NonNull
     public ContentValues getContentValues() {
         ContentValues cv = new ContentValues(16);
+        cv.put(CellBroadcasts.SLOT_INDEX, mSlotIndex);
         cv.put(CellBroadcasts.GEOGRAPHICAL_SCOPE, mGeographicalScope);
         if (mLocation.getPlmn() != null) {
             cv.put(CellBroadcasts.PLMN, mLocation.getPlmn());
@@ -563,6 +579,7 @@
         }
 
         cv.put(CellBroadcasts.MAXIMUM_WAIT_TIME, mMaximumWaitTimeSec);
+        cv.put(CellBroadcasts.SLOT_INDEX, mSlotIndex);
 
         return cv;
     }
@@ -584,6 +601,7 @@
         String body = cursor.getString(cursor.getColumnIndexOrThrow(CellBroadcasts.MESSAGE_BODY));
         int format = cursor.getInt(cursor.getColumnIndexOrThrow(CellBroadcasts.MESSAGE_FORMAT));
         int priority = cursor.getInt(cursor.getColumnIndexOrThrow(CellBroadcasts.MESSAGE_PRIORITY));
+        int slotIndex = cursor.getInt(cursor.getColumnIndexOrThrow(CellBroadcasts.SLOT_INDEX));
 
         String plmn;
         int plmnColumn = cursor.getColumnIndex(CellBroadcasts.PLMN);
@@ -681,7 +699,7 @@
 
         return new SmsCbMessage(format, geoScope, serialNum, location, category,
                 language, body, priority, etwsInfo, cmasInfo, maximumWaitTimeSec, geometries,
-                receivedTimeMillis);
+                receivedTimeMillis, slotIndex);
     }
 
     /**
diff --git a/telephony/java/android/telephony/SmsManager.java b/telephony/java/android/telephony/SmsManager.java
index 71fcf23..f4330fa 100644
--- a/telephony/java/android/telephony/SmsManager.java
+++ b/telephony/java/android/telephony/SmsManager.java
@@ -33,6 +33,7 @@
 import android.database.CursorWindow;
 import android.net.Uri;
 import android.os.Binder;
+import android.os.BaseBundle;
 import android.os.Build;
 import android.os.Bundle;
 import android.os.RemoteException;
@@ -2080,7 +2081,9 @@
         }
     }
 
-    /** callback for providing asynchronous sms messages for financial app. */
+    /**
+     * callback for providing asynchronous sms messages for financial app.
+     */
     public abstract static class FinancialSmsCallback {
         /**
          * Callback to send sms messages back to financial app asynchronously.
@@ -2106,24 +2109,14 @@
      * @param params the parameters to filter SMS messages returned.
      * @param executor the executor on which callback will be invoked.
      * @param callback a callback to receive CursorWindow with SMS messages.
+     *
      */
     @RequiresPermission(android.Manifest.permission.SMS_FINANCIAL_TRANSACTIONS)
     public void getSmsMessagesForFinancialApp(
             Bundle params,
             @NonNull @CallbackExecutor Executor executor,
             @NonNull FinancialSmsCallback callback) {
-        try {
-            ISms iccSms = getISmsServiceOrThrow();
-            iccSms.getSmsMessagesForFinancialApp(
-                    getSubscriptionId(), ActivityThread.currentPackageName(), params,
-                    new IFinancialSmsCallback.Stub() {
-                        public void onGetSmsMessagesForFinancialApp(CursorWindow msgs) {
-                            Binder.withCleanCallingIdentity(() -> executor.execute(
-                                    () -> callback.onFinancialSmsMessages(msgs)));
-                        }});
-        } catch (RemoteException ex) {
-            ex.rethrowFromSystemServer();
-        }
+        // This API is not functional and thus removed to avoid future confusion.
     }
 
     /**
diff --git a/telephony/java/android/telephony/SubscriptionManager.java b/telephony/java/android/telephony/SubscriptionManager.java
index a893288..e288f25 100644
--- a/telephony/java/android/telephony/SubscriptionManager.java
+++ b/telephony/java/android/telephony/SubscriptionManager.java
@@ -2101,26 +2101,13 @@
     /** @hide */
     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023)
     public static boolean isValidSlotIndex(int slotIndex) {
-        return slotIndex >= 0 && slotIndex < TelephonyManager.getDefault().getMaxPhoneCount();
+        return slotIndex >= 0 && slotIndex < TelephonyManager.getDefault().getSupportedModemCount();
     }
 
     /** @hide */
     @UnsupportedAppUsage
     public static boolean isValidPhoneId(int phoneId) {
-        return phoneId >= 0 && phoneId < TelephonyManager.getDefault().getMaxPhoneCount();
-    }
-
-    /**
-     * When getPhoneCount and getMaxPhoneCount return different value, isValidPhoneId being true
-     * doesn't mean the phoneId has a corresponding active slot / logical modem. If a DSDS capable
-     * device is in single SIM mode, phoneId=1 is valid but not active.
-     *
-     * TODO: b/139642279 combine with SubscriptionManager#isValidPhoneId when phone objects
-     * are dynamically allocated instead of always based on getMaxPhoneCount.
-     * @hide
-     */
-    public static boolean isActivePhoneId(int slotIndex) {
-        return slotIndex < TelephonyManager.getDefault().getPhoneCount();
+        return phoneId >= 0 && phoneId < TelephonyManager.getDefault().getSupportedModemCount();
     }
 
     /** @hide */
diff --git a/telephony/java/android/telephony/TelephonyManager.java b/telephony/java/android/telephony/TelephonyManager.java
index 9b0ff6a..03e57e7 100644
--- a/telephony/java/android/telephony/TelephonyManager.java
+++ b/telephony/java/android/telephony/TelephonyManager.java
@@ -65,7 +65,6 @@
 import android.telecom.TelecomManager;
 import android.telephony.Annotation.ApnType;
 import android.telephony.Annotation.CallState;
-import android.telephony.Annotation.DataState;
 import android.telephony.Annotation.NetworkType;
 import android.telephony.Annotation.RadioPowerState;
 import android.telephony.Annotation.SimActivationState;
@@ -283,6 +282,21 @@
     };
 
     /** @hide */
+    @IntDef(prefix = {"MODEM_COUNT_"},
+            value = {
+                    MODEM_COUNT_NO_MODEM,
+                    MODEM_COUNT_SINGLE_MODEM,
+                    MODEM_COUNT_DUAL_MODEM,
+                    MODEM_COUNT_TRI_MODEM
+            })
+    public @interface ModemCount {}
+
+    public static final int MODEM_COUNT_NO_MODEM     = 0;
+    public static final int MODEM_COUNT_SINGLE_MODEM = 1;
+    public static final int MODEM_COUNT_DUAL_MODEM   = 2;
+    public static final int MODEM_COUNT_TRI_MODEM    = 3;
+
+    /** @hide */
     @UnsupportedAppUsage
     public TelephonyManager(Context context) {
       this(context, SubscriptionManager.DEFAULT_SUBSCRIPTION_ID);
@@ -359,12 +373,26 @@
     /**
      * Returns the number of phones available.
      * Returns 0 if none of voice, sms, data is not supported
-     * Returns 1 for Single standby mode (Single SIM functionality)
-     * Returns 2 for Dual standby mode.(Dual SIM functionality)
-     * Returns 3 for Tri standby mode.(Tri SIM functionality)
+     * Returns 1 for Single standby mode (Single SIM functionality).
+     * Returns 2 for Dual standby mode (Dual SIM functionality).
+     * Returns 3 for Tri standby mode (Tri SIM functionality).
+     * @deprecated Use {@link #getActiveModemCount} instead.
      */
+    @Deprecated
     public int getPhoneCount() {
-        int phoneCount = 1;
+        return getActiveModemCount();
+    }
+
+    /**
+     * Returns the number of logical modems currently configured to be activated.
+     *
+     * Returns 0 if none of voice, sms, data is not supported
+     * Returns 1 for Single standby mode (Single SIM functionality).
+     * Returns 2 for Dual standby mode (Dual SIM functionality).
+     * Returns 3 for Tri standby mode (Tri SIM functionality).
+     */
+    public @ModemCount int getActiveModemCount() {
+        int modemCount = 1;
         switch (getMultiSimConfiguration()) {
             case UNKNOWN:
                 ConnectivityManager cm = mContext == null ? null : (ConnectivityManager) mContext
@@ -372,33 +400,30 @@
                 // check for voice and data support, 0 if not supported
                 if (!isVoiceCapable() && !isSmsCapable() && cm != null
                         && !cm.isNetworkSupported(ConnectivityManager.TYPE_MOBILE)) {
-                    phoneCount = 0;
+                    modemCount = MODEM_COUNT_NO_MODEM;
                 } else {
-                    phoneCount = 1;
+                    modemCount = MODEM_COUNT_SINGLE_MODEM;
                 }
                 break;
             case DSDS:
             case DSDA:
-                phoneCount = PhoneConstants.MAX_PHONE_COUNT_DUAL_SIM;
+                modemCount = MODEM_COUNT_DUAL_MODEM;
                 break;
             case TSTS:
-                phoneCount = PhoneConstants.MAX_PHONE_COUNT_TRI_SIM;
+                modemCount = MODEM_COUNT_TRI_MODEM;
                 break;
         }
-        return phoneCount;
+        return modemCount;
     }
 
     /**
-     *
-     * Return how many phone / logical modem can be active simultaneously, in terms of device
+     * Return how many logical modem can be potentially active simultaneously, in terms of hardware
      * capability.
-     * For example, for a dual-SIM capable device, it always returns 2, even if only one logical
-     * modem / SIM is active (aka in single SIM mode).
-     *
-     * TODO: b/139642279 publicize and rename.
-     * @hide
+     * It might return different value from {@link #getActiveModemCount}. For example, for a
+     * dual-SIM capable device operating in single SIM mode (only one logical modem is turned on),
+     * {@link #getActiveModemCount} returns 1 while this API returns 2.
      */
-    public int getMaxPhoneCount() {
+    public @ModemCount int getSupportedModemCount() {
         // TODO: b/139642279 when turning on this feature, remove dependency of
         // PROPERTY_REBOOT_REQUIRED_ON_MODEM_CHANGE and always return result based on
         // PROPERTY_MAX_ACTIVE_MODEMS.
@@ -1171,6 +1196,35 @@
             "android.telephony.extra.VOICEMAIL_SCRAMBLED_PIN_STRING";
 
     /**
+     * Broadcast intent that indicates multi-SIM configuration is changed. For example, it changed
+     * from single SIM capable to dual-SIM capable (DSDS or DSDA) or triple-SIM mode.
+     *
+     * It doesn't indicate how many subscriptions are actually active, or which states SIMs are,
+     * or that all steps during multi-SIM change are done. To know those information you still need
+     * to listen to SIM_STATE changes or active subscription changes.
+     *
+     * See extra of {@link #EXTRA_NUM_OF_ACTIVE_SIM_SUPPORTED} for updated value.
+     */
+    public static final String ACTION_MULTI_SIM_CONFIG_CHANGED =
+            "android.telephony.action.MULTI_SIM_CONFIG_CHANGED";
+
+
+    /**
+     * The number of active SIM supported by current multi-SIM config. It's not related to how many
+     * SIM/subscriptions are currently active.
+     *
+     * For single SIM mode, it's 1.
+     * For DSDS or DSDA mode, it's 2.
+     * For triple-SIM mode, it's 3.
+     *
+     * Extra of {@link #ACTION_MULTI_SIM_CONFIG_CHANGED}.
+     *
+     * type: integer
+     */
+    public static final String EXTRA_NUM_OF_ACTIVE_SIM_SUPPORTED =
+            "android.telephony.extra.NUM_OF_ACTIVE_SIM_SUPPORTED";
+
+    /**
      * @hide
      */
     public static final String USSD_RESPONSE = "USSD_RESPONSE";
@@ -1866,11 +1920,23 @@
     /**
      * Returns the Network Access Identifier (NAI). Return null if NAI is not available.
      *
-     * <p>Requires Permission: {@link android.Manifest.permission#READ_PHONE_STATE READ_PHONE_STATE}
-     * or that the calling app has carrier privileges (see {@link #hasCarrierPrivileges}).
+     * <p>Requires Permission: READ_PRIVILEGED_PHONE_STATE, for the calling app to be the device or
+     * profile owner and have the READ_PHONE_STATE permission, or that the calling app has carrier
+     * privileges (see {@link #hasCarrierPrivileges}). The profile owner is an app that owns a
+     * managed profile on the device; for more details see <a
+     * href="https://developer.android.com/work/managed-profiles">Work profiles</a>. Profile owner
+     * access is deprecated and will be removed in a future release.
+     *
+     * <ul>
+     *     <li>If the calling app's target SDK is API level 28 or lower and the app has the
+     *     READ_PHONE_STATE permission then null is returned.</li>
+     *     <li>If the calling app's target SDK is API level 28 or lower and the app does not have
+     *     the READ_PHONE_STATE permission, or if the calling app is targeting API level 29 or
+     *     higher, then a SecurityException is thrown.</li>
+     * </ul>
      */
-    @SuppressAutoDoc // Blocked by b/72967236 - no support for carrier privileges
-    @RequiresPermission(android.Manifest.permission.READ_PHONE_STATE)
+    @SuppressAutoDoc // No support for device / profile owner or carrier privileges (b/72967236).
+    @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE)
     public String getNai() {
         return getNaiBySubscriberId(getSubId());
     }
@@ -1878,6 +1944,21 @@
     /**
      * Returns the NAI. Return null if NAI is not available.
      *
+     * <p>Requires Permission: READ_PRIVILEGED_PHONE_STATE, for the calling app to be the device or
+     * profile owner and have the READ_PHONE_STATE permission, or that the calling app has carrier
+     * privileges (see {@link #hasCarrierPrivileges}). The profile owner is an app that owns a
+     * managed profile on the device; for more details see <a
+     * href="https://developer.android.com/work/managed-profiles">Work profiles</a>. Profile owner
+     * access is deprecated and will be removed in a future release.
+     *
+     * <ul>
+     *     <li>If the calling app's target SDK is API level 28 or lower and the app has the
+     *     READ_PHONE_STATE permission then null is returned.</li>
+     *     <li>If the calling app's target SDK is API level 28 or lower and the app does not have
+     *     the READ_PHONE_STATE permission, or if the calling app is targeting API level 29 or
+     *     higher, then a SecurityException is thrown.</li>
+     * </ul>
+     *
      *  @param slotIndex of which Nai is returned
      */
     /** {@hide}*/
@@ -2443,7 +2524,14 @@
      * @return the lowercase 2 character ISO-3166 country code, or empty string if not available.
      */
     public String getNetworkCountryIso() {
-        return getNetworkCountryIso(getPhoneId());
+        try {
+            ITelephony telephony = getITelephony();
+            if (telephony == null) return "";
+            return telephony.getNetworkCountryIsoForPhone(getPhoneId(),
+                    null /* no permission check */);
+        } catch (RemoteException ex) {
+            return "";
+        }
     }
 
     /**
@@ -2469,11 +2557,12 @@
     @SystemApi
     @TestApi
     @NonNull
+    @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE)
     public String getNetworkCountryIso(int slotIndex) {
         try {
             ITelephony telephony = getITelephony();
             if (telephony == null) return "";
-            return telephony.getNetworkCountryIsoForPhone(slotIndex);
+            return telephony.getNetworkCountryIsoForPhone(slotIndex, getOpPackageName());
         } catch (RemoteException ex) {
             return "";
         }
@@ -2708,6 +2797,8 @@
     /** Class of broadly defined "4G" networks. {@hide} */
     @UnsupportedAppUsage
     public static final int NETWORK_CLASS_4_G = 3;
+    /** Class of broadly defined "5G" networks. {@hide} */
+    public static final int NETWORK_CLASS_5_G = 4;
 
     /**
      * Return general class of network type, such as "3G" or "4G". In cases
@@ -2740,6 +2831,8 @@
             case NETWORK_TYPE_IWLAN:
             case NETWORK_TYPE_LTE_CA:
                 return NETWORK_CLASS_4_G;
+            case NETWORK_TYPE_NR:
+                return NETWORK_CLASS_5_G;
             default:
                 return NETWORK_CLASS_UNKNOWN;
         }
@@ -6801,6 +6894,40 @@
     }
 
     /**
+     * Replace the contents of the forbidden PLMN SIM file with the provided values.
+     * Passing an empty list will clear the contents of the EFfplmn file.
+     * If the provided list is shorter than the size of EFfplmn, then the list will be padded
+     * up to the file size with 'FFFFFF'. (required by 3GPP TS 31.102 spec 4.2.16)
+     * If the list is longer than the size of EFfplmn, then the file will be written from the
+     * beginning of the list up to the file size.
+     *
+     * <p>Requires Permission: {@link android.Manifest.permission#READ_PHONE_STATE READ_PHONE_STATE}
+     * or that the calling app has carrier privileges (see {@link #hasCarrierPrivileges}).
+     *
+     * @param fplmns a list of PLMNs to be forbidden.
+     *
+     * @return number of PLMNs that were successfully written to the SIM FPLMN list.
+     * This may be less than the number of PLMNs passed in where the SIM file does not have enough
+     * room for all of the values passed in. Return -1 in the event of an unexpected failure
+     */
+    @SuppressAutoDoc // Blocked by b/72967236 - no support for carrier privileges
+    @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE)
+    public int setForbiddenPlmns(@NonNull List<String> fplmns) {
+        try {
+            ITelephony telephony = getITelephony();
+            if (telephony == null) return 0;
+            return telephony.setForbiddenPlmns(
+                    getSubId(), APPTYPE_USIM, fplmns, getOpPackageName());
+        } catch (RemoteException ex) {
+            Rlog.e(TAG, "setForbiddenPlmns RemoteException: " + ex.getMessage());
+        } catch (NullPointerException ex) {
+            // This could happen before phone starts
+            Rlog.e(TAG, "setForbiddenPlmns NullPointerException: " + ex.getMessage());
+        }
+        return 0;
+    }
+
+    /**
      * Get P-CSCF address from PCO after data connection is established or modified.
      * @param apnType the apnType, "ims" for IMS APN, "emergency" for EMERGENCY APN
      * @return array of P-CSCF address
@@ -11383,10 +11510,13 @@
      *  3) APN type is whitelisted. E.g. MMS is whitelisted if
      *  {@link SubscriptionManager#setAlwaysAllowMmsData} is turned on.
      *
+     * @param apnType Value indicating the apn type. Apn types are defined in {@link ApnSetting}.
      * @return whether data is enabled for a apn type.
      *
      * @hide
      */
+    @SystemApi
+    @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE)
     public boolean isDataEnabledForApn(@ApnType int apnType) {
         String pkgForDebug = mContext != null ? mContext.getOpPackageName() : "<unknown>";
         try {
diff --git a/telephony/java/android/telephony/TelephonyScanManager.java b/telephony/java/android/telephony/TelephonyScanManager.java
index 28747da..9ff8515 100644
--- a/telephony/java/android/telephony/TelephonyScanManager.java
+++ b/telephony/java/android/telephony/TelephonyScanManager.java
@@ -104,7 +104,7 @@
 
     private final Looper mLooper;
     private final Messenger mMessenger;
-    private SparseArray<NetworkScanInfo> mScanInfo = new SparseArray<NetworkScanInfo>();
+    private final SparseArray<NetworkScanInfo> mScanInfo = new SparseArray<NetworkScanInfo>();
 
     public TelephonyScanManager() {
         HandlerThread thread = new HandlerThread(TAG);
@@ -204,14 +204,16 @@
         try {
             ITelephony telephony = getITelephony();
             if (telephony != null) {
-                int scanId = telephony.requestNetworkScan(
-                        subId, request, mMessenger, new Binder(), callingPackage);
-                if (scanId == INVALID_SCAN_ID) {
-                    Rlog.e(TAG, "Failed to initiate network scan");
-                    return null;
+                synchronized (mScanInfo) {
+                    int scanId = telephony.requestNetworkScan(
+                            subId, request, mMessenger, new Binder(), callingPackage);
+                    if (scanId == INVALID_SCAN_ID) {
+                        Rlog.e(TAG, "Failed to initiate network scan");
+                        return null;
+                    }
+                    saveScanInfo(scanId, request, executor, callback);
+                    return new NetworkScan(scanId, subId);
                 }
-                saveScanInfo(scanId, request, executor, callback);
-                return new NetworkScan(scanId, subId);
             }
         } catch (RemoteException ex) {
             Rlog.e(TAG, "requestNetworkScan RemoteException", ex);
@@ -223,9 +225,7 @@
 
     private void saveScanInfo(
             int id, NetworkScanRequest request, Executor executor, NetworkScanCallback callback) {
-        synchronized (mScanInfo) {
-            mScanInfo.put(id, new NetworkScanInfo(request, executor, callback));
-        }
+        mScanInfo.put(id, new NetworkScanInfo(request, executor, callback));
     }
 
     private ITelephony getITelephony() {
diff --git a/telephony/java/android/telephony/euicc/EuiccManager.java b/telephony/java/android/telephony/euicc/EuiccManager.java
index cabd4df..5a90cb1 100644
--- a/telephony/java/android/telephony/euicc/EuiccManager.java
+++ b/telephony/java/android/telephony/euicc/EuiccManager.java
@@ -32,6 +32,7 @@
 import android.os.RemoteException;
 import android.os.ServiceManager;
 import android.telephony.TelephonyManager;
+import android.telephony.euicc.EuiccCardManager.ResetOption;
 
 import com.android.internal.telephony.euicc.IEuiccController;
 
@@ -821,17 +822,22 @@
     }
 
     /**
-     * Erase all subscriptions and reset the eUICC.
+     * Erase all operational subscriptions and reset the eUICC.
      *
      * <p>Requires that the calling app has the
      * {@code android.Manifest.permission#WRITE_EMBEDDED_SUBSCRIPTIONS} permission.
      *
      * @param callbackIntent a PendingIntent to launch when the operation completes.
+     *
+     * @deprecated From R, callers should specify a flag for specific set of subscriptions to erase
+     * and use @link{eraseSubscriptionsWithOptions} instead
+     *
      * @hide
      */
     @SystemApi
     @RequiresPermission(Manifest.permission.WRITE_EMBEDDED_SUBSCRIPTIONS)
-    public void eraseSubscriptions(PendingIntent callbackIntent) {
+    @Deprecated
+    public void eraseSubscriptions(@NonNull PendingIntent callbackIntent) {
         if (!isEnabled()) {
             sendUnavailableError(callbackIntent);
             return;
@@ -844,6 +850,32 @@
     }
 
     /**
+     * Erase all specific subscriptions and reset the eUICC.
+     *
+     * <p>Requires that the calling app has the
+     * {@code android.Manifest.permission#WRITE_EMBEDDED_SUBSCRIPTIONS} permission.
+     *
+     * @param options flag indicating specific set of subscriptions to erase
+     * @param callbackIntent a PendingIntent to launch when the operation completes.
+     *
+     * @hide
+     */
+    @SystemApi
+    @RequiresPermission(Manifest.permission.WRITE_EMBEDDED_SUBSCRIPTIONS)
+    public void eraseSubscriptionsWithOptions(
+            @ResetOption int options, @NonNull PendingIntent callbackIntent) {
+        if (!isEnabled()) {
+            sendUnavailableError(callbackIntent);
+            return;
+        }
+        try {
+            getIEuiccController().eraseSubscriptionsWithOptions(mCardId, options, callbackIntent);
+        } catch (RemoteException e) {
+            throw e.rethrowFromSystemServer();
+        }
+    }
+
+    /**
      * Ensure that subscriptions will be retained on the next factory reset.
      *
      * <p>By default, all subscriptions on the eUICC are erased the first time a device boots (ever
diff --git a/telephony/java/android/telephony/ims/ImsMmTelManager.java b/telephony/java/android/telephony/ims/ImsMmTelManager.java
index a1a7fcc..2fad847 100644
--- a/telephony/java/android/telephony/ims/ImsMmTelManager.java
+++ b/telephony/java/android/telephony/ims/ImsMmTelManager.java
@@ -183,19 +183,17 @@
         /**
          * Notifies the framework when the IMS Provider is registered to the IMS network.
          *
-         * @param imsTransportType the radio access technology. Valid values are defined in
-         * {@link android.telephony.AccessNetworkConstants.TransportType}.
+         * @param imsTransportType the radio access technology.
          */
-        public void onRegistered(int imsTransportType) {
+        public void onRegistered(@AccessNetworkConstants.TransportType int imsTransportType) {
         }
 
         /**
          * Notifies the framework when the IMS Provider is trying to register the IMS network.
          *
-         * @param imsTransportType the radio access technology. Valid values are defined in
-         * {@link android.telephony.AccessNetworkConstants.TransportType}.
+         * @param imsTransportType the radio access technology.
          */
-        public void onRegistering(int imsTransportType) {
+        public void onRegistering(@AccessNetworkConstants.TransportType int imsTransportType) {
         }
 
         /**
@@ -207,15 +205,14 @@
         }
 
         /**
-         * A failure has occurred when trying to handover registration to another technology type,
-         * defined in {@link android.telephony.AccessNetworkConstants.TransportType}
+         * A failure has occurred when trying to handover registration to another technology type.
          *
-         * @param imsTransportType The
-         *         {@link android.telephony.AccessNetworkConstants.TransportType}
-         *         transport type that has failed to handover registration to.
+         * @param imsTransportType The transport type that has failed to handover registration to.
          * @param info A {@link ImsReasonInfo} that identifies the reason for failure.
          */
-        public void onTechnologyChangeFailed(int imsTransportType, @Nullable ImsReasonInfo info) {
+        public void onTechnologyChangeFailed(
+                @AccessNetworkConstants.TransportType int imsTransportType,
+                @Nullable ImsReasonInfo info) {
         }
 
         /**
diff --git a/telephony/java/com/android/internal/telephony/ISms.aidl b/telephony/java/com/android/internal/telephony/ISms.aidl
index 7441c26..f3a335d 100644
--- a/telephony/java/com/android/internal/telephony/ISms.aidl
+++ b/telephony/java/com/android/internal/telephony/ISms.aidl
@@ -19,7 +19,6 @@
 import android.app.PendingIntent;
 import android.net.Uri;
 import android.os.Bundle;
-import android.telephony.IFinancialSmsCallback;
 import com.android.internal.telephony.SmsRawData;
 
 /**
@@ -570,17 +569,6 @@
             int subId, String callingPkg, String prefixes, in PendingIntent intent);
 
     /**
-     * Get sms inbox messages for the calling financial app.
-     *
-     * @param subId the SIM id.
-     * @param callingPkg the package name of the calling app.
-     * @param params parameters to filter the sms messages.
-     * @param callback the callback interface to deliver the result.
-     */
-    void getSmsMessagesForFinancialApp(
-        int subId, String callingPkg, in Bundle params, in IFinancialSmsCallback callback);
-
-    /**
      * Check if the destination is a possible premium short code.
      *
      * @param destAddress the destination address to test for possible short code
diff --git a/telephony/java/com/android/internal/telephony/ISmsImplBase.java b/telephony/java/com/android/internal/telephony/ISmsImplBase.java
index aa1f94f..2096325 100644
--- a/telephony/java/com/android/internal/telephony/ISmsImplBase.java
+++ b/telephony/java/com/android/internal/telephony/ISmsImplBase.java
@@ -19,7 +19,6 @@
 import android.app.PendingIntent;
 import android.net.Uri;
 import android.os.Bundle;
-import android.telephony.IFinancialSmsCallback;
 
 import java.util.List;
 
@@ -198,12 +197,6 @@
     }
 
     @Override
-    public void getSmsMessagesForFinancialApp(
-            int subId, String callingPkg, Bundle params, IFinancialSmsCallback callback) {
-        throw new UnsupportedOperationException();
-    }
-
-    @Override
     public int checkSmsShortCodeDestination(
             int subid, String callingApk, String destAddress, String countryIso) {
         throw new UnsupportedOperationException();
diff --git a/telephony/java/com/android/internal/telephony/ITelephony.aidl b/telephony/java/com/android/internal/telephony/ITelephony.aidl
index 866e936..fd7ec56 100644
--- a/telephony/java/com/android/internal/telephony/ITelephony.aidl
+++ b/telephony/java/com/android/internal/telephony/ITelephony.aidl
@@ -302,7 +302,7 @@
      * operator's MCC (Mobile Country Code).
      * @see android.telephony.TelephonyManager#getNetworkCountryIso
      */
-    String getNetworkCountryIsoForPhone(int phoneId);
+    String getNetworkCountryIsoForPhone(int phoneId, String callingPkg);
 
     /**
      * Returns the neighboring cell information of the device.
@@ -1612,6 +1612,18 @@
     String[] getForbiddenPlmns(int subId, int appType, String callingPackage);
 
     /**
+     * Set the forbidden PLMN list from the givven app type (ex APPTYPE_USIM) on a particular
+     * subscription.
+     *
+     * @param subId subId the id of the subscription
+     * @param appType appType the uicc app type, must be USIM or SIM.
+     * @param fplmns plmns the Forbiden plmns list that needed to be written to the SIM.
+     * @param content callingPackage the op Package name.
+     * @return number of fplmns that is successfully written to the SIM
+     */
+    int setForbiddenPlmns(int subId, int appType, in List<String> fplmns, String callingPackage);
+
+    /**
      * Check if phone is in emergency callback mode
      * @return true if phone is in emergency callback mode
      * @param subId the subscription ID that this action applies to.
diff --git a/telephony/java/com/android/internal/telephony/PhoneConstants.java b/telephony/java/com/android/internal/telephony/PhoneConstants.java
index c9ec0f8..c19ae7b 100644
--- a/telephony/java/com/android/internal/telephony/PhoneConstants.java
+++ b/telephony/java/com/android/internal/telephony/PhoneConstants.java
@@ -170,7 +170,7 @@
 
     public static final int RIL_CARD_MAX_APPS    = 8;
 
-    public static final int DEFAULT_CARD_INDEX   = 0;
+    public static final int DEFAULT_SLOT_INDEX   = 0;
 
     public static final int MAX_PHONE_COUNT_SINGLE_SIM = 1;
 
diff --git a/telephony/java/com/android/internal/telephony/cdma/SmsMessage.java b/telephony/java/com/android/internal/telephony/cdma/SmsMessage.java
index d892e55..4654437 100644
--- a/telephony/java/com/android/internal/telephony/cdma/SmsMessage.java
+++ b/telephony/java/com/android/internal/telephony/cdma/SmsMessage.java
@@ -878,8 +878,9 @@
      * Parses a broadcast SMS, possibly containing a CMAS alert.
      *
      * @param plmn the PLMN for a broadcast SMS
+     * @param subId
      */
-    public SmsCbMessage parseBroadcastSms(String plmn) {
+    public SmsCbMessage parseBroadcastSms(String plmn, int subId) {
         BearerData bData = BearerData.decode(mEnvelope.bearerData, mEnvelope.serviceCategory);
         if (bData == null) {
             Rlog.w(LOG_TAG, "BearerData.decode() returned null");
@@ -895,7 +896,7 @@
         return new SmsCbMessage(SmsCbMessage.MESSAGE_FORMAT_3GPP2,
                 SmsCbMessage.GEOGRAPHICAL_SCOPE_PLMN_WIDE, bData.messageId, location,
                 mEnvelope.serviceCategory, bData.getLanguage(), bData.userData.payloadStr,
-                bData.priority, null, bData.cmasWarningInfo);
+                bData.priority, null, bData.cmasWarningInfo, subId);
     }
 
     /**
diff --git a/telephony/java/com/android/internal/telephony/euicc/IEuiccController.aidl b/telephony/java/com/android/internal/telephony/euicc/IEuiccController.aidl
index 2016915..7422863 100644
--- a/telephony/java/com/android/internal/telephony/euicc/IEuiccController.aidl
+++ b/telephony/java/com/android/internal/telephony/euicc/IEuiccController.aidl
@@ -44,5 +44,7 @@
     oneway void updateSubscriptionNickname(int cardId, int subscriptionId, String nickname,
         String callingPackage, in PendingIntent callbackIntent);
     oneway void eraseSubscriptions(int cardId, in PendingIntent callbackIntent);
+    oneway void eraseSubscriptionsWithOptions(
+        int cardId, int options, in PendingIntent callbackIntent);
     oneway void retainSubscriptionsForFactoryReset(int cardId, in PendingIntent callbackIntent);
 }
diff --git a/telephony/java/com/android/internal/telephony/gsm/GsmSmsCbMessage.java b/telephony/java/com/android/internal/telephony/gsm/GsmSmsCbMessage.java
index 6eea118..c3d490a 100644
--- a/telephony/java/com/android/internal/telephony/gsm/GsmSmsCbMessage.java
+++ b/telephony/java/com/android/internal/telephony/gsm/GsmSmsCbMessage.java
@@ -90,9 +90,10 @@
      * Create a new SmsCbMessage object from a header object plus one or more received PDUs.
      *
      * @param pdus PDU bytes
+     * @slotIndex slotIndex for which received sms cb message
      */
     public static SmsCbMessage createSmsCbMessage(Context context, SmsCbHeader header,
-            SmsCbLocation location, byte[][] pdus)
+            SmsCbLocation location, byte[][] pdus, int slotIndex)
             throws IllegalArgumentException {
         long receivedTimeMillis = System.currentTimeMillis();
         if (header.isEtwsPrimaryNotification()) {
@@ -104,7 +105,7 @@
                     header.getSerialNumber(), location, header.getServiceCategory(), null,
                     getEtwsPrimaryMessage(context, header.getEtwsInfo().getWarningType()),
                     SmsCbMessage.MESSAGE_PRIORITY_EMERGENCY, header.getEtwsInfo(),
-                    header.getCmasInfo(), 0, null /* geometries */, receivedTimeMillis);
+                    header.getCmasInfo(), 0, null /* geometries */, receivedTimeMillis, slotIndex);
         } else if (header.isUmtsFormat()) {
             // UMTS format has only 1 PDU
             byte[] pdu = pdus[0];
@@ -138,7 +139,7 @@
                     header.getGeographicalScope(), header.getSerialNumber(), location,
                     header.getServiceCategory(), language, body, priority,
                     header.getEtwsInfo(), header.getCmasInfo(), maximumWaitingTimeSec, geometries,
-                    receivedTimeMillis);
+                    receivedTimeMillis, slotIndex);
         } else {
             String language = null;
             StringBuilder sb = new StringBuilder();
@@ -154,7 +155,7 @@
                     header.getGeographicalScope(), header.getSerialNumber(), location,
                     header.getServiceCategory(), language, sb.toString(), priority,
                     header.getEtwsInfo(), header.getCmasInfo(), 0, null /* geometries */,
-                    receivedTimeMillis);
+                    receivedTimeMillis, slotIndex);
         }
     }
 
@@ -461,7 +462,11 @@
         }
     }
 
-    static final class GeoFencingTriggerMessage {
+    /**
+     * Part of a GSM SMS cell broadcast message which may trigger geo-fencing logic.
+     * @hide
+     */
+    public static final class GeoFencingTriggerMessage {
         /**
          * Indicate the list of active alerts share their warning area coordinates which means the
          * broadcast area is the union of the broadcast areas of the active alerts in this list.
@@ -476,6 +481,11 @@
             this.cbIdentifiers = cbIdentifiers;
         }
 
+        /**
+         * Whether the trigger message indicates that the broadcast areas are shared between all
+         * active alerts.
+         * @return true if broadcast areas are to be shared
+         */
         boolean shouldShareBroadcastArea() {
             return type == TYPE_ACTIVE_ALERT_SHARE_WAC;
         }
diff --git a/telephony/java/com/android/internal/telephony/gsm/SmsCbHeader.java b/telephony/java/com/android/internal/telephony/gsm/SmsCbHeader.java
index 6bbff4b..cbe5211 100644
--- a/telephony/java/com/android/internal/telephony/gsm/SmsCbHeader.java
+++ b/telephony/java/com/android/internal/telephony/gsm/SmsCbHeader.java
@@ -74,22 +74,22 @@
     /**
      * Length of SMS-CB header
      */
-    static final int PDU_HEADER_LENGTH = 6;
+    public static final int PDU_HEADER_LENGTH = 6;
 
     /**
      * GSM pdu format, as defined in 3gpp TS 23.041, section 9.4.1
      */
-    static final int FORMAT_GSM = 1;
+    public static final int FORMAT_GSM = 1;
 
     /**
      * UMTS pdu format, as defined in 3gpp TS 23.041, section 9.4.2
      */
-    static final int FORMAT_UMTS = 2;
+    public static final int FORMAT_UMTS = 2;
 
     /**
-     * GSM pdu format, as defined in 3gpp TS 23.041, section 9.4.1.3
+     * ETWS pdu format, as defined in 3gpp TS 23.041, section 9.4.1.3
      */
-    static final int FORMAT_ETWS_PRIMARY = 3;
+    public static final int FORMAT_ETWS_PRIMARY = 3;
 
     /**
      * Message type value as defined in 3gpp TS 25.324, section 11.1.
@@ -230,43 +230,43 @@
     }
 
     @UnsupportedAppUsage
-    int getGeographicalScope() {
+    public int getGeographicalScope() {
         return mGeographicalScope;
     }
 
     @UnsupportedAppUsage
-    int getSerialNumber() {
+    public int getSerialNumber() {
         return mSerialNumber;
     }
 
     @UnsupportedAppUsage
-    int getServiceCategory() {
+    public int getServiceCategory() {
         return mMessageIdentifier;
     }
 
-    int getDataCodingScheme() {
+    public int getDataCodingScheme() {
         return mDataCodingScheme;
     }
 
-    DataCodingScheme getDataCodingSchemeStructedData() {
+    public DataCodingScheme getDataCodingSchemeStructedData() {
         return mDataCodingSchemeStructedData;
     }
 
     @UnsupportedAppUsage
-    int getPageIndex() {
+    public int getPageIndex() {
         return mPageIndex;
     }
 
     @UnsupportedAppUsage
-    int getNumberOfPages() {
+    public int getNumberOfPages() {
         return mNrOfPages;
     }
 
-    SmsCbEtwsInfo getEtwsInfo() {
+    public SmsCbEtwsInfo getEtwsInfo() {
         return mEtwsInfo;
     }
 
-    SmsCbCmasInfo getCmasInfo() {
+    public SmsCbCmasInfo getCmasInfo() {
         return mCmasInfo;
     }
 
@@ -274,7 +274,7 @@
      * Return whether this broadcast is an emergency (PWS) message type.
      * @return true if this message is emergency type; false otherwise
      */
-    boolean isEmergencyMessage() {
+    public boolean isEmergencyMessage() {
         return mMessageIdentifier >= SmsCbConstants.MESSAGE_ID_PWS_FIRST_IDENTIFIER
                 && mMessageIdentifier <= SmsCbConstants.MESSAGE_ID_PWS_LAST_IDENTIFIER;
     }
@@ -292,7 +292,7 @@
      * Return whether this broadcast is an ETWS primary notification.
      * @return true if this message is an ETWS primary notification; false otherwise
      */
-    boolean isEtwsPrimaryNotification() {
+    public boolean isEtwsPrimaryNotification() {
         return mFormat == FORMAT_ETWS_PRIMARY;
     }
 
@@ -300,7 +300,7 @@
      * Return whether this broadcast is in UMTS format.
      * @return true if this message is in UMTS format; false otherwise
      */
-    boolean isUmtsFormat() {
+    public boolean isUmtsFormat() {
         return mFormat == FORMAT_UMTS;
     }
 
diff --git a/telephony/java/com/android/internal/telephony/uicc/IccUtils.java b/telephony/java/com/android/internal/telephony/uicc/IccUtils.java
index 9c69e2d..f2d4624 100644
--- a/telephony/java/com/android/internal/telephony/uicc/IccUtils.java
+++ b/telephony/java/com/android/internal/telephony/uicc/IccUtils.java
@@ -22,11 +22,13 @@
 import android.graphics.Color;
 import android.telephony.Rlog;
 
+import com.android.internal.annotations.VisibleForTesting;
 import com.android.internal.telephony.GsmAlphabet;
 
 import dalvik.annotation.compat.UnsupportedAppUsage;
 
 import java.io.UnsupportedEncodingException;
+import java.util.List;
 
 /**
  * Various methods, useful for dealing with SIM data.
@@ -34,6 +36,11 @@
 public class IccUtils {
     static final String LOG_TAG="IccUtils";
 
+    // 3GPP specification constants
+    // Spec reference TS 31.102 section 4.2.16
+    @VisibleForTesting
+    static final int FPLMN_BYTE_SIZE = 3;
+
     // A table mapping from a number to a hex character for fast encoding hex strings.
     private static final char[] HEX_CHARS = {
             '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'
@@ -896,4 +903,27 @@
         }
         return 0;
     }
+
+    /**
+     * Encode the Fplmns into byte array to write to EF.
+     *
+     * @param fplmns Array of fplmns to be serialized.
+     * @param dataLength the size of the EF file.
+     * @return the encoded byte array in the correct format for FPLMN file.
+     */
+    public static byte[] encodeFplmns(List<String> fplmns, int dataLength) {
+        byte[] serializedFplmns = new byte[dataLength];
+        int offset = 0;
+        for (String fplmn : fplmns) {
+            if (offset >= dataLength) break;
+            stringToBcdPlmn(fplmn, serializedFplmns, offset);
+            offset += FPLMN_BYTE_SIZE;
+        }
+        //pads to the length of the EF file.
+        while (offset < dataLength) {
+            // required by 3GPP TS 31.102 spec 4.2.16
+            serializedFplmns[offset++] = (byte) 0xff;
+        }
+        return serializedFplmns;
+    }
 }
diff --git a/test-mock/src/android/test/mock/MockContext.java b/test-mock/src/android/test/mock/MockContext.java
index a95b6f1..fcd4701 100644
--- a/test-mock/src/android/test/mock/MockContext.java
+++ b/test-mock/src/android/test/mock/MockContext.java
@@ -758,6 +758,12 @@
 
     /** {@hide} */
     @Override
+    public Context createContextAsUser(UserHandle user) {
+        throw new UnsupportedOperationException();
+    }
+
+    /** {@hide} */
+    @Override
     public int getUserId() {
         throw new UnsupportedOperationException();
     }
diff --git a/tests/Codegen/runTest.sh b/tests/Codegen/runTest.sh
index 614cbb7..0e90dea 100755
--- a/tests/Codegen/runTest.sh
+++ b/tests/Codegen/runTest.sh
@@ -13,9 +13,13 @@
     header_and_eval m -j16 codegen_cli && \
         header_and_eval codegen $ANDROID_BUILD_TOP/frameworks/base/tests/Codegen/src/com/android/codegentest/SampleDataClass.java && \
         header_and_eval codegen $ANDROID_BUILD_TOP/frameworks/base/tests/Codegen/src/com/android/codegentest/SampleWithCustomBuilder.java && \
+        header_and_eval codegen $ANDROID_BUILD_TOP/frameworks/base/tests/Codegen/src/com/android/codegentest/ParcelAllTheThingsDataClass.java && \
+        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 $ANDROID_PRODUCT_OUT/testcases/CodegenTests/arm64/CodegenTests.apk && \
+        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
 
diff --git a/core/java/android/hardware/biometrics/IBiometricConfirmDeviceCredentialCallback.aidl b/tests/Codegen/src/com/android/codegentest/HierrarchicalDataClassBase.aidl
similarity index 68%
copy from core/java/android/hardware/biometrics/IBiometricConfirmDeviceCredentialCallback.aidl
copy to tests/Codegen/src/com/android/codegentest/HierrarchicalDataClassBase.aidl
index 8b35852..ab62c83 100644
--- a/core/java/android/hardware/biometrics/IBiometricConfirmDeviceCredentialCallback.aidl
+++ b/tests/Codegen/src/com/android/codegentest/HierrarchicalDataClassBase.aidl
@@ -14,13 +14,6 @@
  * limitations under the License.
  */
 
-package android.hardware.biometrics;
+package com.android.codegentest;
 
-/**
- * Communication channel between ConfirmDeviceCredential / ConfirmLock* and BiometricService.
- * @hide
- */
-interface IBiometricConfirmDeviceCredentialCallback {
-    // Invoked when authentication should be canceled.
-    oneway void cancel();
-}
\ No newline at end of file
+parcelable HierrarchicalDataClassBase;
diff --git a/tests/Codegen/src/com/android/codegentest/HierrarchicalDataClassBase.java b/tests/Codegen/src/com/android/codegentest/HierrarchicalDataClassBase.java
new file mode 100644
index 0000000..10eba6a
--- /dev/null
+++ b/tests/Codegen/src/com/android/codegentest/HierrarchicalDataClassBase.java
@@ -0,0 +1,104 @@
+/*
+ * 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.codegentest;
+
+import android.os.Parcelable;
+
+import com.android.internal.util.DataClass;
+
+/**
+ * @see HierrarchicalDataClassChild
+ */
+@DataClass(
+        genConstructor = false,
+        genSetters = true)
+public class HierrarchicalDataClassBase implements Parcelable {
+
+    private int mBaseData;
+
+
+
+    // Code below generated by codegen v1.0.7.
+    //
+    // DO NOT MODIFY!
+    // CHECKSTYLE:OFF Generated code
+    //
+    // To regenerate run:
+    // $ codegen $ANDROID_BUILD_TOP/frameworks/base/tests/Codegen/src/com/android/codegentest/HierrarchicalDataClassBase.java
+
+
+    @DataClass.Generated.Member
+    public int getBaseData() {
+        return mBaseData;
+    }
+
+    @DataClass.Generated.Member
+    public HierrarchicalDataClassBase setBaseData(int value) {
+        mBaseData = value;
+        return this;
+    }
+
+    @Override
+    @DataClass.Generated.Member
+    public void writeToParcel(android.os.Parcel dest, int flags) {
+        // You can override field parcelling by defining methods like:
+        // void parcelFieldName(Parcel dest, int flags) { ... }
+
+        dest.writeInt(mBaseData);
+    }
+
+    @Override
+    @DataClass.Generated.Member
+    public int describeContents() { return 0; }
+
+    /** @hide */
+    @SuppressWarnings({"unchecked", "RedundantCast"})
+    @DataClass.Generated.Member
+    protected HierrarchicalDataClassBase(android.os.Parcel in) {
+        // You can override field unparcelling by defining methods like:
+        // static FieldType unparcelFieldName(Parcel in) { ... }
+
+        int baseData = in.readInt();
+
+        this.mBaseData = baseData;
+
+        // onConstructed(); // You can define this method to get a callback
+    }
+
+    @DataClass.Generated.Member
+    public static final @android.annotation.NonNull Parcelable.Creator<HierrarchicalDataClassBase> CREATOR
+            = new Parcelable.Creator<HierrarchicalDataClassBase>() {
+        @Override
+        public HierrarchicalDataClassBase[] newArray(int size) {
+            return new HierrarchicalDataClassBase[size];
+        }
+
+        @Override
+        public HierrarchicalDataClassBase createFromParcel(android.os.Parcel in) {
+            return new HierrarchicalDataClassBase(in);
+        }
+    };
+
+    @DataClass.Generated(
+            time = 1570576455287L,
+            codegenVersion = "1.0.7",
+            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
+    private void __metadata() {}
+
+}
diff --git a/core/java/android/hardware/biometrics/IBiometricConfirmDeviceCredentialCallback.aidl b/tests/Codegen/src/com/android/codegentest/HierrarchicalDataClassChild.aidl
similarity index 68%
copy from core/java/android/hardware/biometrics/IBiometricConfirmDeviceCredentialCallback.aidl
copy to tests/Codegen/src/com/android/codegentest/HierrarchicalDataClassChild.aidl
index 8b35852..a099722 100644
--- a/core/java/android/hardware/biometrics/IBiometricConfirmDeviceCredentialCallback.aidl
+++ b/tests/Codegen/src/com/android/codegentest/HierrarchicalDataClassChild.aidl
@@ -14,13 +14,6 @@
  * limitations under the License.
  */
 
-package android.hardware.biometrics;
+package com.android.codegentest;
 
-/**
- * Communication channel between ConfirmDeviceCredential / ConfirmLock* and BiometricService.
- * @hide
- */
-interface IBiometricConfirmDeviceCredentialCallback {
-    // Invoked when authentication should be canceled.
-    oneway void cancel();
-}
\ No newline at end of file
+parcelable HierrarchicalDataClassChild;
diff --git a/tests/Codegen/src/com/android/codegentest/HierrarchicalDataClassChild.java b/tests/Codegen/src/com/android/codegentest/HierrarchicalDataClassChild.java
new file mode 100644
index 0000000..1085a6a
--- /dev/null
+++ b/tests/Codegen/src/com/android/codegentest/HierrarchicalDataClassChild.java
@@ -0,0 +1,126 @@
+/*
+ * 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.codegentest;
+
+import android.annotation.NonNull;
+import android.os.Parcelable;
+
+import com.android.internal.util.DataClass;
+
+/**
+ * An example of data classes that extend one another.
+ *
+ * Note that some features like constructor generation might not work well due to lack of
+ * information about the superclass when generating code for subclass.
+ *
+ * It is recommended to avoid inheritance in favor of composition for new data classes,
+ * particularly parcelable ones.
+ *
+ * However for legacy classes or where inheritance is desired for allocation efficiency,
+ * you can either use a technique from this example, opting for mutability/setters, or just write
+ * constructors by hand.
+ *
+ * @see HierrarchicalDataClassBase
+ */
+@DataClass(
+        genParcelable = true,
+        genConstructor = false,
+        genSetters = true)
+public class HierrarchicalDataClassChild extends HierrarchicalDataClassBase {
+
+    private @NonNull String mChildData;
+
+
+
+    // Code below generated by codegen v1.0.7.
+    //
+    // DO NOT MODIFY!
+    // CHECKSTYLE:OFF Generated code
+    //
+    // To regenerate run:
+    // $ codegen $ANDROID_BUILD_TOP/frameworks/base/tests/Codegen/src/com/android/codegentest/HierrarchicalDataClassChild.java
+
+
+    @DataClass.Generated.Member
+    public @NonNull String getChildData() {
+        return mChildData;
+    }
+
+    @DataClass.Generated.Member
+    public HierrarchicalDataClassChild setChildData(@NonNull String value) {
+        mChildData = value;
+        com.android.internal.util.AnnotationValidations.validate(
+                NonNull.class, null, mChildData);
+        return this;
+    }
+
+    @Override
+    @DataClass.Generated.Member
+    public void writeToParcel(android.os.Parcel dest, int flags) {
+        // You can override field parcelling by defining methods like:
+        // void parcelFieldName(Parcel dest, int flags) { ... }
+
+        super.writeToParcel(dest, flags);
+
+        dest.writeString(mChildData);
+    }
+
+    @Override
+    @DataClass.Generated.Member
+    public int describeContents() { return 0; }
+
+    /** @hide */
+    @SuppressWarnings({"unchecked", "RedundantCast"})
+    @DataClass.Generated.Member
+    protected HierrarchicalDataClassChild(android.os.Parcel in) {
+        // You can override field unparcelling by defining methods like:
+        // static FieldType unparcelFieldName(Parcel in) { ... }
+
+        super(in);
+
+        String childData = in.readString();
+
+        this.mChildData = childData;
+        com.android.internal.util.AnnotationValidations.validate(
+                NonNull.class, null, mChildData);
+
+        // onConstructed(); // You can define this method to get a callback
+    }
+
+    @DataClass.Generated.Member
+    public static final @NonNull Parcelable.Creator<HierrarchicalDataClassChild> CREATOR
+            = new Parcelable.Creator<HierrarchicalDataClassChild>() {
+        @Override
+        public HierrarchicalDataClassChild[] newArray(int size) {
+            return new HierrarchicalDataClassChild[size];
+        }
+
+        @Override
+        public HierrarchicalDataClassChild createFromParcel(android.os.Parcel in) {
+            return new HierrarchicalDataClassChild(in);
+        }
+    };
+
+    @DataClass.Generated(
+            time = 1570576456245L,
+            codegenVersion = "1.0.7",
+            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
+    private void __metadata() {}
+
+}
diff --git a/tests/Codegen/src/com/android/codegentest/ParcelAllTheThingsDataClass.java b/tests/Codegen/src/com/android/codegentest/ParcelAllTheThingsDataClass.java
new file mode 100644
index 0000000..75ef963
--- /dev/null
+++ b/tests/Codegen/src/com/android/codegentest/ParcelAllTheThingsDataClass.java
@@ -0,0 +1,384 @@
+/*
+ * 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.codegentest;
+
+import android.annotation.NonNull;
+import android.os.Parcel;
+import android.os.Parcelable;
+import android.util.SparseArray;
+import android.util.SparseIntArray;
+
+import com.android.internal.util.AnnotationValidations;
+import com.android.internal.util.DataClass;
+
+import java.util.List;
+import java.util.Map;
+
+/**
+ * Additional test for various parcelling corner-cases.
+ */
+@DataClass(
+        genBuilder = true,
+        genAidl = false,
+        genToString = true)
+public class ParcelAllTheThingsDataClass implements Parcelable {
+
+    @NonNull String[] mStringArray = null;
+    @NonNull int[] mIntArray = null;
+    @NonNull List<String> mStringList = null;
+
+    @NonNull Map<String, SampleWithCustomBuilder> mMap = null;
+    @NonNull Map<String, String> mStringMap = null;
+
+    @NonNull SparseArray<SampleWithCustomBuilder> mSparseArray = null;
+    @NonNull SparseIntArray mSparseIntArray = null;
+
+
+
+    // Code below generated by codegen v1.0.7.
+    //
+    // DO NOT MODIFY!
+    // CHECKSTYLE:OFF Generated code
+    //
+    // To regenerate run:
+    // $ codegen $ANDROID_BUILD_TOP/frameworks/base/tests/Codegen/src/com/android/codegentest/ParcelAllTheThingsDataClass.java
+
+
+    @DataClass.Generated.Member
+    /* package-private */ ParcelAllTheThingsDataClass(
+            @NonNull String[] stringArray,
+            @NonNull int[] intArray,
+            @NonNull List<String> stringList,
+            @NonNull Map<String,SampleWithCustomBuilder> map,
+            @NonNull Map<String,String> stringMap,
+            @NonNull SparseArray<SampleWithCustomBuilder> sparseArray,
+            @NonNull SparseIntArray sparseIntArray) {
+        this.mStringArray = stringArray;
+        AnnotationValidations.validate(
+                NonNull.class, null, mStringArray);
+        this.mIntArray = intArray;
+        AnnotationValidations.validate(
+                NonNull.class, null, mIntArray);
+        this.mStringList = stringList;
+        AnnotationValidations.validate(
+                NonNull.class, null, mStringList);
+        this.mMap = map;
+        AnnotationValidations.validate(
+                NonNull.class, null, mMap);
+        this.mStringMap = stringMap;
+        AnnotationValidations.validate(
+                NonNull.class, null, mStringMap);
+        this.mSparseArray = sparseArray;
+        AnnotationValidations.validate(
+                NonNull.class, null, mSparseArray);
+        this.mSparseIntArray = sparseIntArray;
+        AnnotationValidations.validate(
+                NonNull.class, null, mSparseIntArray);
+
+        // onConstructed(); // You can define this method to get a callback
+    }
+
+    @DataClass.Generated.Member
+    public @NonNull String[] getStringArray() {
+        return mStringArray;
+    }
+
+    @DataClass.Generated.Member
+    public @NonNull int[] getIntArray() {
+        return mIntArray;
+    }
+
+    @DataClass.Generated.Member
+    public @NonNull List<String> getStringList() {
+        return mStringList;
+    }
+
+    @DataClass.Generated.Member
+    public @NonNull Map<String,SampleWithCustomBuilder> getMap() {
+        return mMap;
+    }
+
+    @DataClass.Generated.Member
+    public @NonNull Map<String,String> getStringMap() {
+        return mStringMap;
+    }
+
+    @DataClass.Generated.Member
+    public @NonNull SparseArray<SampleWithCustomBuilder> getSparseArray() {
+        return mSparseArray;
+    }
+
+    @DataClass.Generated.Member
+    public @NonNull SparseIntArray getSparseIntArray() {
+        return mSparseIntArray;
+    }
+
+    @Override
+    @DataClass.Generated.Member
+    public String toString() {
+        // You can override field toString logic by defining methods like:
+        // String fieldNameToString() { ... }
+
+        return "ParcelAllTheThingsDataClass { " +
+                "stringArray = " + java.util.Arrays.toString(mStringArray) + ", " +
+                "intArray = " + java.util.Arrays.toString(mIntArray) + ", " +
+                "stringList = " + mStringList + ", " +
+                "map = " + mMap + ", " +
+                "stringMap = " + mStringMap + ", " +
+                "sparseArray = " + mSparseArray + ", " +
+                "sparseIntArray = " + mSparseIntArray +
+        " }";
+    }
+
+    @Override
+    @DataClass.Generated.Member
+    public void writeToParcel(Parcel dest, int flags) {
+        // You can override field parcelling by defining methods like:
+        // void parcelFieldName(Parcel dest, int flags) { ... }
+
+        dest.writeStringArray(mStringArray);
+        dest.writeIntArray(mIntArray);
+        dest.writeStringList(mStringList);
+        dest.writeMap(mMap);
+        dest.writeMap(mStringMap);
+        dest.writeSparseArray(mSparseArray);
+        dest.writeSparseIntArray(mSparseIntArray);
+    }
+
+    @Override
+    @DataClass.Generated.Member
+    public int describeContents() { return 0; }
+
+    /** @hide */
+    @SuppressWarnings({"unchecked", "RedundantCast"})
+    @DataClass.Generated.Member
+    protected ParcelAllTheThingsDataClass(Parcel in) {
+        // You can override field unparcelling by defining methods like:
+        // static FieldType unparcelFieldName(Parcel in) { ... }
+
+        String[] stringArray = in.createStringArray();
+        int[] intArray = in.createIntArray();
+        List<String> stringList = new java.util.ArrayList<>();
+        in.readStringList(stringList);
+        Map<String,SampleWithCustomBuilder> map = new java.util.LinkedHashMap<>();
+        in.readMap(map, SampleWithCustomBuilder.class.getClassLoader());
+        Map<String,String> stringMap = new java.util.LinkedHashMap<>();
+        in.readMap(stringMap, String.class.getClassLoader());
+        SparseArray<SampleWithCustomBuilder> sparseArray = (SparseArray) in.readSparseArray(SampleWithCustomBuilder.class.getClassLoader());
+        SparseIntArray sparseIntArray = (SparseIntArray) in.readSparseIntArray();
+
+        this.mStringArray = stringArray;
+        AnnotationValidations.validate(
+                NonNull.class, null, mStringArray);
+        this.mIntArray = intArray;
+        AnnotationValidations.validate(
+                NonNull.class, null, mIntArray);
+        this.mStringList = stringList;
+        AnnotationValidations.validate(
+                NonNull.class, null, mStringList);
+        this.mMap = map;
+        AnnotationValidations.validate(
+                NonNull.class, null, mMap);
+        this.mStringMap = stringMap;
+        AnnotationValidations.validate(
+                NonNull.class, null, mStringMap);
+        this.mSparseArray = sparseArray;
+        AnnotationValidations.validate(
+                NonNull.class, null, mSparseArray);
+        this.mSparseIntArray = sparseIntArray;
+        AnnotationValidations.validate(
+                NonNull.class, null, mSparseIntArray);
+
+        // onConstructed(); // You can define this method to get a callback
+    }
+
+    @DataClass.Generated.Member
+    public static final @NonNull Parcelable.Creator<ParcelAllTheThingsDataClass> CREATOR
+            = new Parcelable.Creator<ParcelAllTheThingsDataClass>() {
+        @Override
+        public ParcelAllTheThingsDataClass[] newArray(int size) {
+            return new ParcelAllTheThingsDataClass[size];
+        }
+
+        @Override
+        public ParcelAllTheThingsDataClass createFromParcel(Parcel in) {
+            return new ParcelAllTheThingsDataClass(in);
+        }
+    };
+
+    /**
+     * A builder for {@link ParcelAllTheThingsDataClass}
+     */
+    @SuppressWarnings("WeakerAccess")
+    @DataClass.Generated.Member
+    public static class Builder {
+
+        private @NonNull String[] mStringArray;
+        private @NonNull int[] mIntArray;
+        private @NonNull List<String> mStringList;
+        private @NonNull Map<String,SampleWithCustomBuilder> mMap;
+        private @NonNull Map<String,String> mStringMap;
+        private @NonNull SparseArray<SampleWithCustomBuilder> mSparseArray;
+        private @NonNull SparseIntArray mSparseIntArray;
+
+        private long mBuilderFieldsSet = 0L;
+
+        public Builder() {
+        }
+
+        @DataClass.Generated.Member
+        public @NonNull Builder setStringArray(@NonNull String... value) {
+            checkNotUsed();
+            mBuilderFieldsSet |= 0x1;
+            mStringArray = value;
+            return this;
+        }
+
+        @DataClass.Generated.Member
+        public @NonNull Builder setIntArray(@NonNull int... value) {
+            checkNotUsed();
+            mBuilderFieldsSet |= 0x2;
+            mIntArray = value;
+            return this;
+        }
+
+        @DataClass.Generated.Member
+        public @NonNull Builder setStringList(@NonNull List<String> value) {
+            checkNotUsed();
+            mBuilderFieldsSet |= 0x4;
+            mStringList = value;
+            return this;
+        }
+
+        /** @see #setStringList */
+        @DataClass.Generated.Member
+        public @NonNull Builder addStringList(String value) {
+            // You can refine this method's name by providing item's singular name, e.g.:
+            // @DataClass.PluralOf("item")) mItems = ...
+
+            if (mStringList == null) setStringList(new java.util.ArrayList<>());
+            mStringList.add(value);
+            return this;
+        }
+
+        @DataClass.Generated.Member
+        public @NonNull Builder setMap(@NonNull Map<String,SampleWithCustomBuilder> value) {
+            checkNotUsed();
+            mBuilderFieldsSet |= 0x8;
+            mMap = value;
+            return this;
+        }
+
+        /** @see #setMap */
+        @DataClass.Generated.Member
+        public @NonNull Builder addMap(String key, SampleWithCustomBuilder value) {
+            // You can refine this method's name by providing item's singular name, e.g.:
+            // @DataClass.PluralOf("item")) mItems = ...
+
+            if (mMap == null) setMap(new java.util.LinkedHashMap());
+            mMap.put(key, value);
+            return this;
+        }
+
+        @DataClass.Generated.Member
+        public @NonNull Builder setStringMap(@NonNull Map<String,String> value) {
+            checkNotUsed();
+            mBuilderFieldsSet |= 0x10;
+            mStringMap = value;
+            return this;
+        }
+
+        /** @see #setStringMap */
+        @DataClass.Generated.Member
+        public @NonNull Builder addStringMap(String key, String value) {
+            // You can refine this method's name by providing item's singular name, e.g.:
+            // @DataClass.PluralOf("item")) mItems = ...
+
+            if (mStringMap == null) setStringMap(new java.util.LinkedHashMap());
+            mStringMap.put(key, value);
+            return this;
+        }
+
+        @DataClass.Generated.Member
+        public @NonNull Builder setSparseArray(@NonNull SparseArray<SampleWithCustomBuilder> value) {
+            checkNotUsed();
+            mBuilderFieldsSet |= 0x20;
+            mSparseArray = value;
+            return this;
+        }
+
+        @DataClass.Generated.Member
+        public @NonNull Builder setSparseIntArray(@NonNull SparseIntArray value) {
+            checkNotUsed();
+            mBuilderFieldsSet |= 0x40;
+            mSparseIntArray = value;
+            return this;
+        }
+
+        /** Builds the instance. This builder should not be touched after calling this! */
+        public ParcelAllTheThingsDataClass build() {
+            checkNotUsed();
+            mBuilderFieldsSet |= 0x80; // Mark builder used
+
+            if ((mBuilderFieldsSet & 0x1) == 0) {
+                mStringArray = null;
+            }
+            if ((mBuilderFieldsSet & 0x2) == 0) {
+                mIntArray = null;
+            }
+            if ((mBuilderFieldsSet & 0x4) == 0) {
+                mStringList = null;
+            }
+            if ((mBuilderFieldsSet & 0x8) == 0) {
+                mMap = null;
+            }
+            if ((mBuilderFieldsSet & 0x10) == 0) {
+                mStringMap = null;
+            }
+            if ((mBuilderFieldsSet & 0x20) == 0) {
+                mSparseArray = null;
+            }
+            if ((mBuilderFieldsSet & 0x40) == 0) {
+                mSparseIntArray = null;
+            }
+            ParcelAllTheThingsDataClass o = new ParcelAllTheThingsDataClass(
+                    mStringArray,
+                    mIntArray,
+                    mStringList,
+                    mMap,
+                    mStringMap,
+                    mSparseArray,
+                    mSparseIntArray);
+            return o;
+        }
+
+        private void checkNotUsed() {
+            if ((mBuilderFieldsSet & 0x80) != 0) {
+                throw new IllegalStateException(
+                        "This Builder should not be reused. Use a new Builder instance instead");
+            }
+        }
+    }
+
+    @DataClass.Generated(
+            time = 1570576454326L,
+            codegenVersion = "1.0.7",
+            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)")
+    @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 66c7d06..14010a9 100644
--- a/tests/Codegen/src/com/android/codegentest/SampleDataClass.java
+++ b/tests/Codegen/src/com/android/codegentest/SampleDataClass.java
@@ -342,7 +342,7 @@
 
 
 
-    // Code below generated by codegen v1.0.3.
+    // Code below generated by codegen v1.0.7.
     //
     // DO NOT MODIFY!
     // CHECKSTYLE:OFF Generated code
@@ -1290,6 +1290,123 @@
     @DataClass.Generated.Member
     public int describeContents() { return 0; }
 
+    /** @hide */
+    @SuppressWarnings({"unchecked", "RedundantCast"})
+    @DataClass.Generated.Member
+    /* package-private */ SampleDataClass(Parcel in) {
+        // You can override field unparcelling by defining methods like:
+        // static FieldType unparcelFieldName(Parcel in) { ... }
+
+        long flg = in.readLong();
+        int num = in.readInt();
+        int num2 = in.readInt();
+        int num4 = in.readInt();
+        String name = (flg & 0x8) == 0 ? null : in.readString();
+        String name2 = in.readString();
+        String name4 = in.readString();
+        AccessibilityNodeInfo otherParcelable = (flg & 0x40) == 0 ? null : (AccessibilityNodeInfo) in.readTypedObject(AccessibilityNodeInfo.CREATOR);
+        Date date = sParcellingForDate.unparcel(in);
+        Pattern pattern = sParcellingForPattern.unparcel(in);
+        List<LinkAddress> linkAddresses2 = new ArrayList<>();
+        in.readParcelableList(linkAddresses2, LinkAddress.class.getClassLoader());
+        ArrayList<LinkAddress> linkAddresses = new ArrayList<>();
+        in.readParcelableList(linkAddresses, LinkAddress.class.getClassLoader());
+        LinkAddress[] linkAddresses4 = (flg & 0x800) == 0 ? null : (LinkAddress[]) in.createTypedArray(LinkAddress.CREATOR);
+        String stateName = in.readString();
+        int flags = in.readInt();
+        int state = in.readInt();
+        CharSequence _charSeq = (CharSequence) in.readCharSequence();
+        LinkAddress[] linkAddresses5 = (flg & 0x10000) == 0 ? null : (LinkAddress[]) in.createTypedArray(LinkAddress.CREATOR);
+        int stringRes = in.readInt();
+        int dayOfWeek = in.readInt();
+        float[] coords = in.createFloatArray();
+
+        this.mNum = num;
+        this.mNum2 = num2;
+        this.mNum4 = num4;
+        this.mName = name;
+        this.mName2 = name2;
+        AnnotationValidations.validate(
+                NonNull.class, null, mName2);
+        this.mName4 = name4;
+        AnnotationValidations.validate(
+                NonNull.class, null, mName4);
+        this.mOtherParcelable = otherParcelable;
+        this.mDate = date;
+        AnnotationValidations.validate(
+                NonNull.class, null, mDate);
+        this.mPattern = pattern;
+        AnnotationValidations.validate(
+                NonNull.class, null, mPattern);
+        this.mLinkAddresses2 = linkAddresses2;
+        AnnotationValidations.validate(
+                NonNull.class, null, mLinkAddresses2);
+        this.mLinkAddresses = linkAddresses;
+        AnnotationValidations.validate(
+                NonNull.class, null, mLinkAddresses);
+        this.mLinkAddresses4 = linkAddresses4;
+        this.mStateName = stateName;
+
+        if (!(Objects.equals(mStateName, STATE_NAME_UNDEFINED))
+                && !(Objects.equals(mStateName, STATE_NAME_ON))
+                && !(Objects.equals(mStateName, STATE_NAME_OFF))) {
+            throw new java.lang.IllegalArgumentException(
+                    "stateName was " + mStateName + " but must be one of: "
+                            + "STATE_NAME_UNDEFINED(" + STATE_NAME_UNDEFINED + "), "
+                            + "STATE_NAME_ON(" + STATE_NAME_ON + "), "
+                            + "STATE_NAME_OFF(" + STATE_NAME_OFF + ")");
+        }
+
+        AnnotationValidations.validate(
+                NonNull.class, null, mStateName);
+        this.mFlags = flags;
+
+        Preconditions.checkFlagsArgument(
+                mFlags,
+                FLAG_MANUAL_REQUEST
+                        | FLAG_COMPATIBILITY_MODE_REQUEST
+                        | FLAG_AUGMENTED_REQUEST);
+        this.mState = state;
+
+        if (!(mState == STATE_UNDEFINED)
+                && !(mState == STATE_ON)
+                && !(mState == STATE_OFF)) {
+            throw new java.lang.IllegalArgumentException(
+                    "state was " + mState + " but must be one of: "
+                            + "STATE_UNDEFINED(" + STATE_UNDEFINED + "), "
+                            + "STATE_ON(" + STATE_ON + "), "
+                            + "STATE_OFF(" + STATE_OFF + ")");
+        }
+
+        this.charSeq = _charSeq;
+        AnnotationValidations.validate(
+                NonNull.class, null, charSeq);
+        this.mLinkAddresses5 = linkAddresses5;
+        this.mStringRes = stringRes;
+        AnnotationValidations.validate(
+                StringRes.class, null, mStringRes);
+        this.mDayOfWeek = dayOfWeek;
+        AnnotationValidations.validate(
+                android.annotation.IntRange.class, null, mDayOfWeek,
+                "from", 0,
+                "to", 6);
+        this.mCoords = coords;
+        AnnotationValidations.validate(
+                Size.class, null, mCoords.length,
+                "value", 2);
+        AnnotationValidations.validate(
+                NonNull.class, null, mCoords);
+        int coordsSize = mCoords.length;
+        for (int i = 0; i < coordsSize; i++) {
+            AnnotationValidations.validate(
+                    FloatRange.class, null, mCoords[i],
+                    "from", 0f);
+        }
+
+
+        onConstructed();
+    }
+
     @DataClass.Generated.Member
     public static final @NonNull Parcelable.Creator<SampleDataClass> CREATOR
             = new Parcelable.Creator<SampleDataClass>() {
@@ -1299,55 +1416,8 @@
         }
 
         @Override
-        @SuppressWarnings({"unchecked", "RedundantCast"})
         public SampleDataClass createFromParcel(Parcel in) {
-            // You can override field unparcelling by defining methods like:
-            // static FieldType unparcelFieldName(Parcel in) { ... }
-
-            long flg = in.readLong();
-            int num = in.readInt();
-            int num2 = in.readInt();
-            int num4 = in.readInt();
-            String name = (flg & 0x8) == 0 ? null : in.readString();
-            String name2 = in.readString();
-            String name4 = in.readString();
-            AccessibilityNodeInfo otherParcelable = (flg & 0x40) == 0 ? null : (AccessibilityNodeInfo) in.readTypedObject(AccessibilityNodeInfo.CREATOR);
-            Date date = sParcellingForDate.unparcel(in);
-            Pattern pattern = sParcellingForPattern.unparcel(in);
-            List<LinkAddress> linkAddresses2 = new ArrayList<>();
-            in.readParcelableList(linkAddresses2, LinkAddress.class.getClassLoader());
-            ArrayList<LinkAddress> linkAddresses = new ArrayList<>();
-            in.readParcelableList(linkAddresses, LinkAddress.class.getClassLoader());
-            LinkAddress[] linkAddresses4 = (flg & 0x800) == 0 ? null : (LinkAddress[]) in.createTypedArray(LinkAddress.CREATOR);
-            String stateName = in.readString();
-            int flags = in.readInt();
-            int state = in.readInt();
-            CharSequence _charSeq = (CharSequence) in.readCharSequence();
-            LinkAddress[] linkAddresses5 = (flg & 0x10000) == 0 ? null : (LinkAddress[]) in.createTypedArray(LinkAddress.CREATOR);
-            int stringRes = in.readInt();
-            int dayOfWeek = in.readInt();
-            float[] coords = in.createFloatArray();
-            return new SampleDataClass(
-                    num,
-                    num2,
-                    num4,
-                    name,
-                    name2,
-                    name4,
-                    otherParcelable,
-                    date,
-                    pattern,
-                    linkAddresses2,
-                    linkAddresses,
-                    linkAddresses4,
-                    stateName,
-                    flags,
-                    state,
-                    _charSeq,
-                    linkAddresses5,
-                    stringRes,
-                    dayOfWeek,
-                    coords);
+            return new SampleDataClass(in);
         }
     };
 
@@ -1798,8 +1868,8 @@
     }
 
     @DataClass.Generated(
-            time = 1569956013899L,
-            codegenVersion = "1.0.3",
+            time = 1570576452225L,
+            codegenVersion = "1.0.7",
             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/SampleDataClassTest.java b/tests/Codegen/src/com/android/codegentest/SampleDataClassTest.java
index 6636207..c7a7735 100644
--- a/tests/Codegen/src/com/android/codegentest/SampleDataClassTest.java
+++ b/tests/Codegen/src/com/android/codegentest/SampleDataClassTest.java
@@ -25,9 +25,14 @@
 import static org.junit.Assert.assertSame;
 import static org.junit.Assert.assertThat;
 
+import static java.util.concurrent.TimeUnit.SECONDS;
+
 import android.net.LinkAddress;
+import android.os.Bundle;
 import android.os.Parcel;
 import android.os.Parcelable;
+import android.util.SparseArray;
+import android.util.SparseIntArray;
 
 import androidx.test.runner.AndroidJUnit4;
 
@@ -36,6 +41,9 @@
 
 import java.util.Arrays;
 import java.util.Date;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
 import java.util.concurrent.atomic.AtomicInteger;
 
 /**
@@ -209,6 +217,32 @@
         newBuilder().setDayOfWeek(42).build();
     }
 
+    @Test
+    public void testDataStructures_parcelCorrectly() {
+        SampleWithCustomBuilder otherParcelable = new SampleWithCustomBuilder.Builder().setDelay(3, SECONDS).build();
+
+        ParcelAllTheThingsDataClass instance = new ParcelAllTheThingsDataClass.Builder()
+                .setIntArray(40, 41)
+                .addMap("foo", otherParcelable)
+                .setSparseArray(new SparseArray<SampleWithCustomBuilder>() {{
+                    put(45, otherParcelable);
+                }})
+                .setSparseIntArray(new SparseIntArray() {{
+                    put(48, 49);
+                }})
+                .addStringMap("foo2", "fooValue")
+                .setStringArray("foo", "bar")
+                .addStringList("foo")
+                .build();
+
+        ParcelAllTheThingsDataClass unparceledInstance =
+                parcelAndUnparcel(instance, ParcelAllTheThingsDataClass.CREATOR);
+
+        // SparseArray and friends don't implement equals
+        // so just compare string representations instead
+        assertEquals(instance.toString(), unparceledInstance.toString());
+    }
+
     private static <T extends Parcelable> T parcelAndUnparcel(
             T original, Parcelable.Creator<T> creator) {
         Parcel p = Parcel.obtain();
diff --git a/tests/Codegen/src/com/android/codegentest/SampleWithCustomBuilder.java b/tests/Codegen/src/com/android/codegentest/SampleWithCustomBuilder.java
index c6bc8de..b5f6c73 100644
--- a/tests/Codegen/src/com/android/codegentest/SampleWithCustomBuilder.java
+++ b/tests/Codegen/src/com/android/codegentest/SampleWithCustomBuilder.java
@@ -17,14 +17,16 @@
 package com.android.codegentest;
 
 import android.annotation.NonNull;
+import android.os.Parcel;
+import android.os.Parcelable;
 import android.os.SystemClock;
 
 import com.android.internal.util.DataClass;
 
 import java.util.concurrent.TimeUnit;
 
-@DataClass(genBuilder = true)
-public class SampleWithCustomBuilder {
+@DataClass(genBuilder = true, genAidl = false, genToString = true)
+public class SampleWithCustomBuilder implements Parcelable {
 
     long delayAmount = 0;
     @NonNull
@@ -73,8 +75,17 @@
     }
 
 
+    private static TimeUnit unparcelDelayUnit(Parcel p) {
+        return TimeUnit.values()[p.readInt()];
+    }
 
-    // Code below generated by codegen v1.0.3.
+    private void parcelDelayUnit(Parcel p, int flags) {
+        p.writeInt(delayUnit.ordinal());
+    }
+
+
+
+    // Code below generated by codegen v1.0.7.
     //
     // DO NOT MODIFY!
     // CHECKSTYLE:OFF Generated code
@@ -112,6 +123,68 @@
         return creationTimestamp;
     }
 
+    @Override
+    @DataClass.Generated.Member
+    public String toString() {
+        // You can override field toString logic by defining methods like:
+        // String fieldNameToString() { ... }
+
+        return "SampleWithCustomBuilder { " +
+                "delayAmount = " + delayAmount + ", " +
+                "delayUnit = " + delayUnit + ", " +
+                "creationTimestamp = " + creationTimestamp +
+        " }";
+    }
+
+    @Override
+    @DataClass.Generated.Member
+    public void writeToParcel(Parcel dest, int flags) {
+        // You can override field parcelling by defining methods like:
+        // void parcelFieldName(Parcel dest, int flags) { ... }
+
+        dest.writeLong(delayAmount);
+        parcelDelayUnit(dest, flags);
+        dest.writeLong(creationTimestamp);
+    }
+
+    @Override
+    @DataClass.Generated.Member
+    public int describeContents() { return 0; }
+
+    /** @hide */
+    @SuppressWarnings({"unchecked", "RedundantCast"})
+    @DataClass.Generated.Member
+    protected SampleWithCustomBuilder(Parcel in) {
+        // You can override field unparcelling by defining methods like:
+        // static FieldType unparcelFieldName(Parcel in) { ... }
+
+        long _delayAmount = in.readLong();
+        TimeUnit _delayUnit = unparcelDelayUnit(in);
+        long _creationTimestamp = in.readLong();
+
+        this.delayAmount = _delayAmount;
+        this.delayUnit = _delayUnit;
+        com.android.internal.util.AnnotationValidations.validate(
+                NonNull.class, null, delayUnit);
+        this.creationTimestamp = _creationTimestamp;
+
+        // onConstructed(); // You can define this method to get a callback
+    }
+
+    @DataClass.Generated.Member
+    public static final @NonNull Parcelable.Creator<SampleWithCustomBuilder> CREATOR
+            = new Parcelable.Creator<SampleWithCustomBuilder>() {
+        @Override
+        public SampleWithCustomBuilder[] newArray(int size) {
+            return new SampleWithCustomBuilder[size];
+        }
+
+        @Override
+        public SampleWithCustomBuilder createFromParcel(Parcel in) {
+            return new SampleWithCustomBuilder(in);
+        }
+    };
+
     /**
      * A builder for {@link SampleWithCustomBuilder}
      */
@@ -176,10 +249,10 @@
     }
 
     @DataClass.Generated(
-            time = 1569956014908L,
-            codegenVersion = "1.0.3",
+            time = 1570576453295L,
+            codegenVersion = "1.0.7",
             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\nclass SampleWithCustomBuilder extends java.lang.Object implements []\n@com.android.internal.util.DataClass(genBuilder=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 []")
+            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
     private void __metadata() {}
 
diff --git a/tests/Codegen/src/com/android/codegentest/StaleDataclassDetectorFalsePositivesTest.java b/tests/Codegen/src/com/android/codegentest/StaleDataclassDetectorFalsePositivesTest.java
new file mode 100644
index 0000000..0ce8aba
--- /dev/null
+++ b/tests/Codegen/src/com/android/codegentest/StaleDataclassDetectorFalsePositivesTest.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.codegentest;
+
+import android.annotation.NonNull;
+
+import com.android.internal.util.DataClass;
+
+/**
+ * Test for some false positive pitfalls for
+ * {@link android.processor.staledataclass.StaleDataclassProcessor}
+ *
+ * Relies on the detector being run, failing the build should any of things here falsely
+ * register as stale.
+ */
+@DataClass(genConstructor = false, genBuilder = false)
+public class StaleDataclassDetectorFalsePositivesTest {
+
+    /** Interfaces should be ignored */
+    public interface SomeListener {
+        void onEvent();
+    }
+
+    /** Enums should be ignored */
+    private enum SomeEnum { ONE, TWO }
+
+    /** Annotations should be ignored */
+    public @interface SomeAnnotation {}
+
+    /* Static initializers should be ignored */
+    static {}
+
+    /* Initializers should be ignored */
+    {}
+
+    /** Unrelated methods should be noted, without triggering staleness false positives */
+    public @NonNull String someMethod(int param) { return null; }
+
+
+
+    // Code below generated by codegen v1.0.7.
+    //
+    // DO NOT MODIFY!
+    // CHECKSTYLE:OFF Generated code
+    //
+    // To regenerate run:
+    // $ codegen $ANDROID_BUILD_TOP/frameworks/base/tests/Codegen/src/com/android/codegentest/StaleDataclassDetectorFalsePositivesTest.java
+
+
+    @DataClass.Generated(
+            time = 1570576457249L,
+            codegenVersion = "1.0.7",
+            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
+    private void __metadata() {}
+
+}
diff --git a/tests/MirrorSurfaceTest/Android.bp b/tests/MirrorSurfaceTest/Android.bp
new file mode 100644
index 0000000..e359c64
--- /dev/null
+++ b/tests/MirrorSurfaceTest/Android.bp
@@ -0,0 +1,6 @@
+android_test {
+    name: "MirrorSurfaceTest",
+    srcs: ["src/**/*.java"],
+    platform_apis: true,
+    certificate: "platform",
+}
diff --git a/tests/MirrorSurfaceTest/AndroidManifest.xml b/tests/MirrorSurfaceTest/AndroidManifest.xml
new file mode 100644
index 0000000..123cd0f
--- /dev/null
+++ b/tests/MirrorSurfaceTest/AndroidManifest.xml
@@ -0,0 +1,34 @@
+<?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 xmlns:android="http://schemas.android.com/apk/res/android"
+          package="com.google.android.test.mirrorsurface">
+    <uses-permission android:name="android.permission.ACCESS_SURFACE_FLINGER"/>
+    <uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW" />
+
+    <application android:label="MirrorSurfaceTest">
+        <activity android:name=".MirrorSurfaceActivity"
+                  android:label="Mirror Surface"
+                  android:configChanges="orientation|screenSize">
+            <intent-filter>
+                <action android:name="android.intent.action.MAIN"/>
+                <category android:name="android.intent.category.LAUNCHER"/>
+                <category android:name="android.intent.category.DEFAULT"/>
+            </intent-filter>
+        </activity>
+    </application>
+</manifest>
diff --git a/tests/MirrorSurfaceTest/res/layout/activity_mirror_surface.xml b/tests/MirrorSurfaceTest/res/layout/activity_mirror_surface.xml
new file mode 100644
index 0000000..73b509f
--- /dev/null
+++ b/tests/MirrorSurfaceTest/res/layout/activity_mirror_surface.xml
@@ -0,0 +1,111 @@
+<?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.
+  -->
+
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+              android:layout_width="match_parent"
+              android:layout_height="match_parent"
+              android:orientation="vertical">
+
+    <LinearLayout
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:layout_gravity="center_horizontal"
+        android:layout_marginTop="20dp"
+        android:orientation="horizontal">
+
+        <Button
+            android:id="@+id/mirror_button"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:layout_marginRight="20dp"
+            android:text="Mirror"
+            android:textSize="20dp" />
+
+        <Button
+            android:id="@+id/remove_mirror_button"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:layout_marginRight="20dp"
+            android:text="Remove Mirror"
+            android:textSize="20dp" />
+    </LinearLayout>
+
+    <LinearLayout
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:layout_marginLeft="40dp"
+        android:layout_marginRight="40dp"
+        android:layout_marginTop="10dp"
+        android:orientation="horizontal">
+
+        <TextView
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:layout_marginRight="20dp"
+            android:text="SCALE: " />
+
+        <EditText
+            android:hint="0.5"
+            android:id="@+id/scale"
+            android:layout_width="match_parent"
+            android:layout_height="wrap_content"
+            android:inputType="numberDecimal" />
+    </LinearLayout>
+
+    <LinearLayout
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:layout_marginLeft="40dp"
+        android:layout_marginRight="40dp"
+        android:layout_marginTop="10dp"
+        android:orientation="horizontal">
+
+        <TextView
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:layout_marginRight="20dp"
+            android:text="DISPLAY FRAME: " />
+
+        <EditText
+            android:hint="0, 0, 20, 20"
+            android:id="@+id/displayFrame"
+            android:layout_width="match_parent"
+            android:layout_height="wrap_content"
+            android:inputType="numberDecimal|text"/>
+    </LinearLayout>
+
+    <LinearLayout
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:layout_marginLeft="40dp"
+        android:layout_marginRight="40dp"
+        android:layout_marginTop="10dp"
+        android:orientation="horizontal">
+
+        <TextView
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:layout_marginRight="20dp"
+            android:text="SOURCE POSITION: " />
+
+        <TextView
+            android:id="@+id/sourcePosition"
+            android:layout_width="match_parent"
+            android:layout_height="wrap_content"
+            android:inputType="numberDecimal|text"/>
+    </LinearLayout>
+</LinearLayout>
diff --git a/tests/MirrorSurfaceTest/res/layout/move_view.xml b/tests/MirrorSurfaceTest/res/layout/move_view.xml
new file mode 100644
index 0000000..5707700
--- /dev/null
+++ b/tests/MirrorSurfaceTest/res/layout/move_view.xml
@@ -0,0 +1,101 @@
+<?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.
+  -->
+
+<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
+             android:layout_width="wrap_content"
+             android:layout_height="wrap_content"
+             android:layout_margin="20dp"
+             android:gravity="center">
+
+    <RelativeLayout
+        android:id="@+id/arrows"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content">
+
+        <ImageButton
+            android:id="@+id/up_arrow"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:layout_toEndOf="@+id/right_arrow"
+            android:background="@android:color/holo_green_light"
+            android:padding="10dp"
+            android:src="@android:drawable/arrow_up_float" />
+
+        <ImageButton
+            android:id="@+id/down_arrow"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:layout_below="@+id/up_arrow"
+            android:layout_marginTop="80dp"
+            android:layout_toEndOf="@+id/right_arrow"
+            android:background="@android:color/holo_green_light"
+            android:padding="10dp"
+            android:src="@android:drawable/arrow_down_float" />
+
+        <ImageButton
+            android:id="@+id/right_arrow"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:layout_alignTop="@+id/up_arrow"
+            android:layout_alignBottom="@+id/down_arrow"
+            android:layout_marginTop="55dp"
+            android:layout_marginEnd="15dp"
+            android:layout_marginBottom="55dp"
+            android:background="@android:color/holo_green_light"
+            android:paddingLeft="10dp"
+            android:paddingRight="10dp"
+            android:rotation="90"
+            android:src="@android:drawable/arrow_down_float" />
+
+        <ImageButton
+            android:id="@+id/left_arrow"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:layout_alignTop="@+id/up_arrow"
+            android:layout_alignBottom="@+id/down_arrow"
+            android:layout_marginStart="15dp"
+            android:layout_marginTop="55dp"
+            android:layout_marginBottom="55dp"
+            android:layout_toEndOf="@+id/down_arrow"
+            android:background="@android:color/holo_green_light"
+            android:paddingLeft="10dp"
+            android:paddingRight="10dp"
+            android:rotation="-90"
+            android:src="@android:drawable/arrow_down_float" />
+    </RelativeLayout>
+
+    <RelativeLayout
+
+        android:layout_gravity="center"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content">
+
+        <Button
+            android:id="@+id/zoom_in_button"
+            android:layout_width="40dp"
+            android:layout_marginBottom="-8dp"
+            android:layout_height="40dp"
+            android:text="+" />
+
+        <Button
+            android:layout_below="@+id/zoom_in_button"
+            android:id="@+id/zoom_out_button"
+            android:layout_width="40dp"
+            android:layout_height="40dp"
+            android:text="-" />
+    </RelativeLayout>
+</FrameLayout>
\ No newline at end of file
diff --git a/tests/MirrorSurfaceTest/src/com/google/android/test/mirrorsurface/MirrorSurfaceActivity.java b/tests/MirrorSurfaceTest/src/com/google/android/test/mirrorsurface/MirrorSurfaceActivity.java
new file mode 100644
index 0000000..b863713
--- /dev/null
+++ b/tests/MirrorSurfaceTest/src/com/google/android/test/mirrorsurface/MirrorSurfaceActivity.java
@@ -0,0 +1,441 @@
+/*
+ * 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.test.mirrorsurface;
+
+
+import android.app.Activity;
+import android.graphics.Canvas;
+import android.graphics.Color;
+import android.graphics.PixelFormat;
+import android.graphics.Point;
+import android.graphics.Rect;
+import android.os.Bundle;
+import android.os.Handler;
+import android.os.RemoteException;
+import android.util.DisplayMetrics;
+import android.view.Gravity;
+import android.view.IWindowManager;
+import android.view.MotionEvent;
+import android.view.Surface;
+import android.view.SurfaceControl;
+import android.view.View;
+import android.view.ViewGroup;
+import android.view.WindowManager;
+import android.view.WindowManagerGlobal;
+import android.widget.EditText;
+import android.widget.LinearLayout;
+import android.widget.TextView;
+
+public class MirrorSurfaceActivity extends Activity implements View.OnClickListener,
+        View.OnLongClickListener, View.OnTouchListener {
+    private static final int BORDER_SIZE = 10;
+    private static final int DEFAULT_SCALE = 2;
+    private static final int DEFAULT_BORDER_COLOR = Color.argb(255, 255, 153, 0);
+    private static final int MOVE_FRAME_AMOUNT = 20;
+
+    private IWindowManager mIWm;
+    private WindowManager mWm;
+
+    private SurfaceControl mSurfaceControl = new SurfaceControl();
+    private SurfaceControl mBorderSc;
+
+    private SurfaceControl.Transaction mTransaction = new SurfaceControl.Transaction();
+    private View mOverlayView;
+    private View mArrowOverlay;
+
+    private Rect mDisplayBounds = new Rect();
+
+    private EditText mScaleText;
+    private EditText mDisplayFrameText;
+    private TextView mSourcePositionText;
+
+    private Rect mTmpRect = new Rect();
+    private final Surface mTmpSurface = new Surface();
+
+    private boolean mHasMirror;
+
+    private Rect mCurrFrame = new Rect();
+    private float mCurrScale = DEFAULT_SCALE;
+
+    private final Handler mHandler = new Handler();
+
+    private MoveMirrorRunnable mMoveMirrorRunnable = new MoveMirrorRunnable();
+    private boolean mIsPressedDown = false;
+
+    private int mDisplayId;
+
+    @Override
+    protected void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+
+        setContentView(R.layout.activity_mirror_surface);
+        mWm = (WindowManager) getSystemService(WINDOW_SERVICE);
+        mIWm = WindowManagerGlobal.getWindowManagerService();
+
+        DisplayMetrics displayMetrics = new DisplayMetrics();
+        getWindowManager().getDefaultDisplay().getMetrics(displayMetrics);
+        mDisplayBounds.set(0, 0, displayMetrics.widthPixels, displayMetrics.heightPixels);
+
+        mScaleText = findViewById(R.id.scale);
+        mDisplayFrameText = findViewById(R.id.displayFrame);
+        mSourcePositionText = findViewById(R.id.sourcePosition);
+
+        mCurrFrame.set(0, 0, mDisplayBounds.width() / 2, mDisplayBounds.height() / 2);
+        mCurrScale = DEFAULT_SCALE;
+
+        mDisplayId = getWindowManager().getDefaultDisplay().getDisplayId();
+        updateEditTexts();
+
+        findViewById(R.id.mirror_button).setOnClickListener(view -> {
+            if (mArrowOverlay == null) {
+                createArrowOverlay();
+            }
+            createOrUpdateMirror();
+        });
+
+        findViewById(R.id.remove_mirror_button).setOnClickListener(v -> {
+            removeMirror();
+            removeArrowOverlay();
+        });
+
+        createMirrorOverlay();
+    }
+
+    private void updateEditTexts() {
+        mDisplayFrameText.setText(
+                String.format("%s, %s, %s, %s", mCurrFrame.left, mCurrFrame.top, mCurrFrame.right,
+                        mCurrFrame.bottom));
+        mScaleText.setText(String.valueOf(mCurrScale));
+    }
+
+    @Override
+    protected void onDestroy() {
+        super.onDestroy();
+        if (mOverlayView != null) {
+            removeMirror();
+            mWm.removeView(mOverlayView);
+            mOverlayView = null;
+        }
+        removeArrowOverlay();
+    }
+
+    private void createArrowOverlay() {
+        mArrowOverlay = getLayoutInflater().inflate(R.layout.move_view, null);
+        WindowManager.LayoutParams arrowParams = new WindowManager.LayoutParams(
+                ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT,
+                WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY,
+                WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL
+                        | WindowManager.LayoutParams.FLAG_WATCH_OUTSIDE_TOUCH
+                        | WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE,
+                PixelFormat.RGBA_8888);
+        arrowParams.gravity = Gravity.RIGHT | Gravity.BOTTOM;
+        mWm.addView(mArrowOverlay, arrowParams);
+
+        View leftArrow = mArrowOverlay.findViewById(R.id.left_arrow);
+        View topArrow = mArrowOverlay.findViewById(R.id.up_arrow);
+        View rightArrow = mArrowOverlay.findViewById(R.id.right_arrow);
+        View bottomArrow = mArrowOverlay.findViewById(R.id.down_arrow);
+
+        leftArrow.setOnClickListener(this);
+        topArrow.setOnClickListener(this);
+        rightArrow.setOnClickListener(this);
+        bottomArrow.setOnClickListener(this);
+
+        leftArrow.setOnLongClickListener(this);
+        topArrow.setOnLongClickListener(this);
+        rightArrow.setOnLongClickListener(this);
+        bottomArrow.setOnLongClickListener(this);
+
+        leftArrow.setOnTouchListener(this);
+        topArrow.setOnTouchListener(this);
+        rightArrow.setOnTouchListener(this);
+        bottomArrow.setOnTouchListener(this);
+
+        mArrowOverlay.findViewById(R.id.zoom_in_button).setOnClickListener(v -> {
+            if (mCurrScale <= 1) {
+                mCurrScale *= 2;
+            } else {
+                mCurrScale += 0.5;
+            }
+
+            updateMirror(mCurrFrame, mCurrScale);
+        });
+        mArrowOverlay.findViewById(R.id.zoom_out_button).setOnClickListener(v -> {
+            if (mCurrScale <= 1) {
+                mCurrScale /= 2;
+            } else {
+                mCurrScale -= 0.5;
+            }
+
+            updateMirror(mCurrFrame, mCurrScale);
+        });
+    }
+
+    private void removeArrowOverlay() {
+        if (mArrowOverlay != null) {
+            mWm.removeView(mArrowOverlay);
+            mArrowOverlay = null;
+        }
+    }
+
+    private void createMirrorOverlay() {
+        mOverlayView = new LinearLayout(this);
+        WindowManager.LayoutParams params = new WindowManager.LayoutParams(mDisplayBounds.width(),
+                mDisplayBounds.height(),
+                WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY,
+                WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE
+                        | WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE,
+                PixelFormat.RGBA_8888);
+        params.gravity = Gravity.LEFT | Gravity.TOP;
+        params.setTitle("Mirror Overlay");
+        mOverlayView.setSystemUiVisibility(View.SYSTEM_UI_FLAG_LAYOUT_STABLE
+                | View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION
+                | View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
+                | View.SYSTEM_UI_FLAG_FULLSCREEN
+                | View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY
+                | View.SYSTEM_UI_FLAG_HIDE_NAVIGATION);
+
+        mWm.addView(mOverlayView, params);
+
+    }
+
+    private void removeMirror() {
+        if (mSurfaceControl.isValid()) {
+            mTransaction.remove(mSurfaceControl).apply();
+        }
+        mHasMirror = false;
+    }
+
+    private void createOrUpdateMirror() {
+        if (mHasMirror) {
+            updateMirror(getDisplayFrame(), getScale());
+        } else {
+            createMirror(getDisplayFrame(), getScale());
+        }
+
+    }
+
+    private Rect getDisplayFrame() {
+        mTmpRect.setEmpty();
+        String[] frameVals = mDisplayFrameText.getText().toString().split("\\s*,\\s*");
+        if (frameVals.length != 4) {
+            return mTmpRect;
+        }
+
+        try {
+            mTmpRect.set(Integer.parseInt(frameVals[0]), Integer.parseInt(frameVals[1]),
+                    Integer.parseInt(frameVals[2]), Integer.parseInt(frameVals[3]));
+        } catch (Exception e) {
+            mTmpRect.setEmpty();
+        }
+
+        return mTmpRect;
+    }
+
+    private float getScale() {
+        try {
+            return Float.parseFloat(mScaleText.getText().toString());
+        } catch (Exception e) {
+            return -1;
+        }
+    }
+
+    private void createMirror(Rect displayFrame, float scale) {
+        boolean success = false;
+        try {
+            success = mIWm.mirrorDisplay(mDisplayId, mSurfaceControl);
+        } catch (RemoteException e) {
+        }
+
+        if (!success) {
+            return;
+        }
+
+        if (!mSurfaceControl.isValid()) {
+            return;
+        }
+
+        mHasMirror = true;
+
+        mBorderSc = new SurfaceControl.Builder()
+                .setName("Mirror Border")
+                .setBufferSize(1, 1)
+                .setFormat(PixelFormat.TRANSLUCENT)
+                .build();
+
+        updateMirror(displayFrame, scale);
+
+        mTransaction
+                .show(mSurfaceControl)
+                .reparent(mSurfaceControl, mOverlayView.getViewRootImpl().getSurfaceControl())
+                .setLayer(mBorderSc, 1)
+                .show(mBorderSc)
+                .reparent(mBorderSc, mSurfaceControl)
+                .apply();
+    }
+
+    private void updateMirror(Rect displayFrame, float scale) {
+        if (displayFrame.isEmpty()) {
+            Rect bounds = mDisplayBounds;
+            int defaultCropW = Math.round(bounds.width() / 2);
+            int defaultCropH = Math.round(bounds.height() / 2);
+            displayFrame.set(0, 0, defaultCropW, defaultCropH);
+        }
+
+        if (scale <= 0) {
+            scale = DEFAULT_SCALE;
+        }
+
+        mCurrFrame.set(displayFrame);
+        mCurrScale = scale;
+
+        int width = (int) Math.ceil(displayFrame.width() / scale);
+        int height = (int) Math.ceil(displayFrame.height() / scale);
+
+        Rect sourceBounds = getSourceBounds(displayFrame, scale);
+
+        mTransaction.setGeometry(mSurfaceControl, sourceBounds, displayFrame, Surface.ROTATION_0)
+                .setPosition(mBorderSc, sourceBounds.left, sourceBounds.top)
+                .setBufferSize(mBorderSc, width, height)
+                .apply();
+
+        drawBorder(mBorderSc, width, height, (int) Math.ceil(BORDER_SIZE / scale));
+
+        mSourcePositionText.setText(sourceBounds.left + ", " + sourceBounds.top);
+        mDisplayFrameText.setText(
+                String.format("%s, %s, %s, %s", mCurrFrame.left, mCurrFrame.top, mCurrFrame.right,
+                        mCurrFrame.bottom));
+        mScaleText.setText(String.valueOf(mCurrScale));
+    }
+
+    private void drawBorder(SurfaceControl borderSc, int width, int height, int borderSize) {
+        mTmpSurface.copyFrom(borderSc);
+
+        Canvas c = null;
+        try {
+            c = mTmpSurface.lockCanvas(null);
+        } catch (IllegalArgumentException | Surface.OutOfResourcesException e) {
+        }
+        if (c == null) {
+            return;
+        }
+
+        // Top
+        c.save();
+        c.clipRect(new Rect(0, 0, width, borderSize));
+        c.drawColor(DEFAULT_BORDER_COLOR);
+        c.restore();
+        // Left
+        c.save();
+        c.clipRect(new Rect(0, 0, borderSize, height));
+        c.drawColor(DEFAULT_BORDER_COLOR);
+        c.restore();
+        // Right
+        c.save();
+        c.clipRect(new Rect(width - borderSize, 0, width, height));
+        c.drawColor(DEFAULT_BORDER_COLOR);
+        c.restore();
+        // Bottom
+        c.save();
+        c.clipRect(new Rect(0, height - borderSize, width, height));
+        c.drawColor(DEFAULT_BORDER_COLOR);
+        c.restore();
+
+        mTmpSurface.unlockCanvasAndPost(c);
+    }
+
+    @Override
+    public void onClick(View v) {
+        Point offset = findOffset(v);
+        moveMirrorForArrows(offset.x, offset.y);
+    }
+
+    @Override
+    public boolean onLongClick(View v) {
+        mIsPressedDown = true;
+        Point point = findOffset(v);
+        mMoveMirrorRunnable.mXOffset = point.x;
+        mMoveMirrorRunnable.mYOffset = point.y;
+        mHandler.post(mMoveMirrorRunnable);
+        return false;
+    }
+
+    @Override
+    public boolean onTouch(View v, MotionEvent event) {
+        switch (event.getAction()) {
+            case MotionEvent.ACTION_UP:
+            case MotionEvent.ACTION_CANCEL:
+                mIsPressedDown = false;
+                break;
+        }
+        return false;
+    }
+
+    private Point findOffset(View v) {
+        Point offset = new Point(0, 0);
+
+        switch (v.getId()) {
+            case R.id.up_arrow:
+                offset.y = -MOVE_FRAME_AMOUNT;
+                break;
+            case R.id.down_arrow:
+                offset.y = MOVE_FRAME_AMOUNT;
+                break;
+            case R.id.right_arrow:
+                offset.x = -MOVE_FRAME_AMOUNT;
+                break;
+            case R.id.left_arrow:
+                offset.x = MOVE_FRAME_AMOUNT;
+                break;
+        }
+
+        return offset;
+    }
+
+    private void moveMirrorForArrows(int xOffset, int yOffset) {
+        mCurrFrame.offset(xOffset, yOffset);
+
+        updateMirror(mCurrFrame, mCurrScale);
+    }
+
+    /**
+     * Calculates the desired source bounds. This will be the area under from the center of  the
+     * displayFrame, factoring in scale.
+     */
+    private Rect getSourceBounds(Rect displayFrame, float scale) {
+        int halfWidth = displayFrame.width() / 2;
+        int halfHeight = displayFrame.height() / 2;
+        int left = displayFrame.left + (halfWidth - (int) (halfWidth / scale));
+        int right = displayFrame.right - (halfWidth - (int) (halfWidth / scale));
+        int top = displayFrame.top + (halfHeight - (int) (halfHeight / scale));
+        int bottom = displayFrame.bottom - (halfHeight - (int) (halfHeight / scale));
+        return new Rect(left, top, right, bottom);
+    }
+
+    class MoveMirrorRunnable implements Runnable {
+        int mXOffset = 0;
+        int mYOffset = 0;
+
+        @Override
+        public void run() {
+            if (mIsPressedDown) {
+                moveMirrorForArrows(mXOffset, mYOffset);
+                mHandler.postDelayed(mMoveMirrorRunnable, 150);
+            }
+        }
+    }
+}
diff --git a/tests/net/common/java/android/net/LinkPropertiesTest.java b/tests/net/common/java/android/net/LinkPropertiesTest.java
index b0464d9..ae8285b 100644
--- a/tests/net/common/java/android/net/LinkPropertiesTest.java
+++ b/tests/net/common/java/android/net/LinkPropertiesTest.java
@@ -99,6 +99,7 @@
         assertFalse(lp.isIpv4Provisioned());
         assertFalse(lp.isIpv6Provisioned());
         assertFalse(lp.isPrivateDnsActive());
+        assertFalse(lp.isWakeOnLanSupported());
     }
 
     private LinkProperties makeTestObject() {
@@ -120,6 +121,7 @@
         lp.setMtu(MTU);
         lp.setTcpBufferSizes(TCP_BUFFER_SIZES);
         lp.setNat64Prefix(new IpPrefix("2001:db8:0:64::/96"));
+        lp.setWakeOnLanSupported(true);
         return lp;
     }
 
@@ -158,6 +160,9 @@
         assertTrue(source.isIdenticalTcpBufferSizes(target));
         assertTrue(target.isIdenticalTcpBufferSizes(source));
 
+        assertTrue(source.isIdenticalWakeOnLan(target));
+        assertTrue(target.isIdenticalWakeOnLan(source));
+
         // Check result of equals().
         assertTrue(source.equals(target));
         assertTrue(target.equals(source));
@@ -1057,4 +1062,13 @@
         lp.clear();
         assertFalse(lp.isPrivateDnsActive());
     }
+
+    @Test
+    public void testWakeOnLanSupported() {
+        final LinkProperties lp = makeTestObject();
+        assertTrue(lp.isWakeOnLanSupported());
+
+        lp.clear();
+        assertFalse(lp.isWakeOnLanSupported());
+    }
 }
diff --git a/tests/net/java/com/android/server/ConnectivityServiceTest.java b/tests/net/java/com/android/server/ConnectivityServiceTest.java
index 5bfd647..cf3fba8 100644
--- a/tests/net/java/com/android/server/ConnectivityServiceTest.java
+++ b/tests/net/java/com/android/server/ConnectivityServiceTest.java
@@ -207,7 +207,7 @@
 import com.android.server.net.NetworkPolicyManagerInternal;
 import com.android.testutils.ExceptionUtils;
 import com.android.testutils.HandlerUtilsKt;
-import com.android.testutils.RecorderCallback.CallbackRecord;
+import com.android.testutils.RecorderCallback.CallbackEntry;
 import com.android.testutils.TestableNetworkCallback;
 
 import org.junit.After;
@@ -274,6 +274,7 @@
     private static final String CLAT_PREFIX = "v4-";
     private static final String MOBILE_IFNAME = "test_rmnet_data0";
     private static final String WIFI_IFNAME = "test_wlan0";
+    private static final String WIFI_WOL_IFNAME = "test_wlan_wol";
     private static final String[] EMPTY_STRING_ARRAY = new String[0];
 
     private MockContext mServiceContext;
@@ -343,6 +344,12 @@
                             "mobile_mms,2,0,2,60000,true",
                     });
 
+            when(mResources.getStringArray(
+                    com.android.internal.R.array.config_wakeonlan_supported_interfaces))
+                    .thenReturn(new String[]{
+                            WIFI_WOL_IFNAME,
+                    });
+
             mContentResolver = new MockContentResolver();
             mContentResolver.addProvider(Settings.AUTHORITY, settingsProvider);
         }
@@ -1478,12 +1485,12 @@
         }
 
         @Override
-        public <T extends CallbackRecord> T expectCallback(final KClass<T> type, final HasNetwork n,
+        public <T extends CallbackEntry> T expectCallback(final KClass<T> type, final HasNetwork n,
                 final long timeoutMs) {
             final T callback = super.expectCallback(type, n, timeoutMs);
-            if (callback instanceof CallbackRecord.Losing) {
+            if (callback instanceof CallbackEntry.Losing) {
                 // TODO : move this to the specific test(s) needing this rather than here.
-                final CallbackRecord.Losing losing = (CallbackRecord.Losing) callback;
+                final CallbackEntry.Losing losing = (CallbackEntry.Losing) callback;
                 final int maxMsToLive = losing.getMaxMsToLive();
                 String msg = String.format(
                         "Invalid linger time value %d, must be between %d and %d",
@@ -1544,16 +1551,16 @@
 
         cv = waitForConnectivityBroadcasts(2);
         mWiFiNetworkAgent.disconnect();
-        genericNetworkCallback.expectCallback(CallbackRecord.LOST, mWiFiNetworkAgent);
-        wifiNetworkCallback.expectCallback(CallbackRecord.LOST, mWiFiNetworkAgent);
+        genericNetworkCallback.expectCallback(CallbackEntry.LOST, mWiFiNetworkAgent);
+        wifiNetworkCallback.expectCallback(CallbackEntry.LOST, mWiFiNetworkAgent);
         cellNetworkCallback.assertNoCallback();
         waitFor(cv);
         assertNoCallbacks(genericNetworkCallback, wifiNetworkCallback, cellNetworkCallback);
 
         cv = waitForConnectivityBroadcasts(1);
         mCellNetworkAgent.disconnect();
-        genericNetworkCallback.expectCallback(CallbackRecord.LOST, mCellNetworkAgent);
-        cellNetworkCallback.expectCallback(CallbackRecord.LOST, mCellNetworkAgent);
+        genericNetworkCallback.expectCallback(CallbackEntry.LOST, mCellNetworkAgent);
+        cellNetworkCallback.expectCallback(CallbackEntry.LOST, mCellNetworkAgent);
         waitFor(cv);
         assertNoCallbacks(genericNetworkCallback, wifiNetworkCallback, cellNetworkCallback);
 
@@ -1574,21 +1581,21 @@
         mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
         mWiFiNetworkAgent.connect(true);
         genericNetworkCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
-        genericNetworkCallback.expectCallback(CallbackRecord.LOSING, mCellNetworkAgent);
+        genericNetworkCallback.expectCallback(CallbackEntry.LOSING, mCellNetworkAgent);
         genericNetworkCallback.expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, mWiFiNetworkAgent);
         wifiNetworkCallback.expectAvailableThenValidatedCallbacks(mWiFiNetworkAgent);
-        cellNetworkCallback.expectCallback(CallbackRecord.LOSING, mCellNetworkAgent);
+        cellNetworkCallback.expectCallback(CallbackEntry.LOSING, mCellNetworkAgent);
         assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetwork());
         assertNoCallbacks(genericNetworkCallback, wifiNetworkCallback, cellNetworkCallback);
 
         mWiFiNetworkAgent.disconnect();
-        genericNetworkCallback.expectCallback(CallbackRecord.LOST, mWiFiNetworkAgent);
-        wifiNetworkCallback.expectCallback(CallbackRecord.LOST, mWiFiNetworkAgent);
+        genericNetworkCallback.expectCallback(CallbackEntry.LOST, mWiFiNetworkAgent);
+        wifiNetworkCallback.expectCallback(CallbackEntry.LOST, mWiFiNetworkAgent);
         assertNoCallbacks(genericNetworkCallback, wifiNetworkCallback, cellNetworkCallback);
 
         mCellNetworkAgent.disconnect();
-        genericNetworkCallback.expectCallback(CallbackRecord.LOST, mCellNetworkAgent);
-        cellNetworkCallback.expectCallback(CallbackRecord.LOST, mCellNetworkAgent);
+        genericNetworkCallback.expectCallback(CallbackEntry.LOST, mCellNetworkAgent);
+        cellNetworkCallback.expectCallback(CallbackEntry.LOST, mCellNetworkAgent);
         assertNoCallbacks(genericNetworkCallback, wifiNetworkCallback, cellNetworkCallback);
     }
 
@@ -1628,7 +1635,7 @@
         // We then get LOSING when wifi validates and cell is outscored.
         callback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
         // TODO: Investigate sending validated before losing.
-        callback.expectCallback(CallbackRecord.LOSING, mCellNetworkAgent);
+        callback.expectCallback(CallbackEntry.LOSING, mCellNetworkAgent);
         callback.expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, mWiFiNetworkAgent);
         defaultCallback.expectAvailableDoubleValidatedCallbacks(mWiFiNetworkAgent);
         assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetwork());
@@ -1637,15 +1644,15 @@
         mEthernetNetworkAgent.connect(true);
         callback.expectAvailableCallbacksUnvalidated(mEthernetNetworkAgent);
         // TODO: Investigate sending validated before losing.
-        callback.expectCallback(CallbackRecord.LOSING, mWiFiNetworkAgent);
+        callback.expectCallback(CallbackEntry.LOSING, mWiFiNetworkAgent);
         callback.expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, mEthernetNetworkAgent);
         defaultCallback.expectAvailableDoubleValidatedCallbacks(mEthernetNetworkAgent);
         assertEquals(mEthernetNetworkAgent.getNetwork(), mCm.getActiveNetwork());
         assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
 
         mEthernetNetworkAgent.disconnect();
-        callback.expectCallback(CallbackRecord.LOST, mEthernetNetworkAgent);
-        defaultCallback.expectCallback(CallbackRecord.LOST, mEthernetNetworkAgent);
+        callback.expectCallback(CallbackEntry.LOST, mEthernetNetworkAgent);
+        defaultCallback.expectCallback(CallbackEntry.LOST, mEthernetNetworkAgent);
         defaultCallback.expectAvailableCallbacksValidated(mWiFiNetworkAgent);
         assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
 
@@ -1661,7 +1668,7 @@
                 newNetwork = mWiFiNetworkAgent;
 
             }
-            callback.expectCallback(CallbackRecord.LOSING, oldNetwork);
+            callback.expectCallback(CallbackEntry.LOSING, oldNetwork);
             // TODO: should we send an AVAILABLE callback to newNetwork, to indicate that it is no
             // longer lingering?
             defaultCallback.expectAvailableCallbacksValidated(newNetwork);
@@ -1675,7 +1682,7 @@
         // We expect a notification about the capabilities change, and nothing else.
         defaultCallback.expectCapabilitiesWithout(NET_CAPABILITY_NOT_METERED, mWiFiNetworkAgent);
         defaultCallback.assertNoCallback();
-        callback.expectCallback(CallbackRecord.LOST, mWiFiNetworkAgent);
+        callback.expectCallback(CallbackEntry.LOST, mWiFiNetworkAgent);
         assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
 
         // Wifi no longer satisfies our listen, which is for an unmetered network.
@@ -1684,11 +1691,11 @@
 
         // Disconnect our test networks.
         mWiFiNetworkAgent.disconnect();
-        defaultCallback.expectCallback(CallbackRecord.LOST, mWiFiNetworkAgent);
+        defaultCallback.expectCallback(CallbackEntry.LOST, mWiFiNetworkAgent);
         defaultCallback.expectAvailableCallbacksValidated(mCellNetworkAgent);
         assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
         mCellNetworkAgent.disconnect();
-        defaultCallback.expectCallback(CallbackRecord.LOST, mCellNetworkAgent);
+        defaultCallback.expectCallback(CallbackEntry.LOST, mCellNetworkAgent);
         waitForIdle();
         assertEquals(null, mCm.getActiveNetwork());
 
@@ -1719,8 +1726,8 @@
         assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
 
         mWiFiNetworkAgent.disconnect();
-        callback.expectCallback(CallbackRecord.LOST, mWiFiNetworkAgent);
-        defaultCallback.expectCallback(CallbackRecord.LOST, mWiFiNetworkAgent);
+        callback.expectCallback(CallbackEntry.LOST, mWiFiNetworkAgent);
+        defaultCallback.expectCallback(CallbackEntry.LOST, mWiFiNetworkAgent);
         defaultCallback.expectAvailableCallbacksUnvalidated(mCellNetworkAgent);
         assertEquals(mCellNetworkAgent.getNetwork(), mCm.getActiveNetwork());
         assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
@@ -1731,15 +1738,15 @@
         mWiFiNetworkAgent.adjustScore(50);
         mWiFiNetworkAgent.connect(false);   // Score: 70
         callback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
-        callback.expectCallback(CallbackRecord.LOSING, mCellNetworkAgent);
+        callback.expectCallback(CallbackEntry.LOSING, mCellNetworkAgent);
         defaultCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
         assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetwork());
         assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
 
         // Tear down wifi.
         mWiFiNetworkAgent.disconnect();
-        callback.expectCallback(CallbackRecord.LOST, mWiFiNetworkAgent);
-        defaultCallback.expectCallback(CallbackRecord.LOST, mWiFiNetworkAgent);
+        callback.expectCallback(CallbackEntry.LOST, mWiFiNetworkAgent);
+        defaultCallback.expectCallback(CallbackEntry.LOST, mWiFiNetworkAgent);
         defaultCallback.expectAvailableCallbacksUnvalidated(mCellNetworkAgent);
         assertEquals(mCellNetworkAgent.getNetwork(), mCm.getActiveNetwork());
         assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
@@ -1750,19 +1757,19 @@
         mWiFiNetworkAgent.connect(true);
         callback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
         // TODO: Investigate sending validated before losing.
-        callback.expectCallback(CallbackRecord.LOSING, mCellNetworkAgent);
+        callback.expectCallback(CallbackEntry.LOSING, mCellNetworkAgent);
         callback.expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, mWiFiNetworkAgent);
         defaultCallback.expectAvailableThenValidatedCallbacks(mWiFiNetworkAgent);
         assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetwork());
         assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
 
         mWiFiNetworkAgent.disconnect();
-        callback.expectCallback(CallbackRecord.LOST, mWiFiNetworkAgent);
-        defaultCallback.expectCallback(CallbackRecord.LOST, mWiFiNetworkAgent);
+        callback.expectCallback(CallbackEntry.LOST, mWiFiNetworkAgent);
+        defaultCallback.expectCallback(CallbackEntry.LOST, mWiFiNetworkAgent);
         defaultCallback.expectAvailableCallbacksUnvalidated(mCellNetworkAgent);
         mCellNetworkAgent.disconnect();
-        callback.expectCallback(CallbackRecord.LOST, mCellNetworkAgent);
-        defaultCallback.expectCallback(CallbackRecord.LOST, mCellNetworkAgent);
+        callback.expectCallback(CallbackEntry.LOST, mCellNetworkAgent);
+        defaultCallback.expectCallback(CallbackEntry.LOST, mCellNetworkAgent);
         waitForIdle();
         assertEquals(null, mCm.getActiveNetwork());
 
@@ -1777,7 +1784,7 @@
         defaultCallback.expectAvailableDoubleValidatedCallbacks(mWiFiNetworkAgent);
         callback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
         // TODO: Investigate sending validated before losing.
-        callback.expectCallback(CallbackRecord.LOSING, mCellNetworkAgent);
+        callback.expectCallback(CallbackEntry.LOSING, mCellNetworkAgent);
         callback.expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, mWiFiNetworkAgent);
         assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
 
@@ -1788,13 +1795,13 @@
         // TODO: should this cause an AVAILABLE callback, to indicate that the network is no longer
         // lingering?
         mCm.unregisterNetworkCallback(noopCallback);
-        callback.expectCallback(CallbackRecord.LOSING, mCellNetworkAgent);
+        callback.expectCallback(CallbackEntry.LOSING, mCellNetworkAgent);
 
         // Similar to the above: lingering can start even after the lingered request is removed.
         // Disconnect wifi and switch to cell.
         mWiFiNetworkAgent.disconnect();
-        callback.expectCallback(CallbackRecord.LOST, mWiFiNetworkAgent);
-        defaultCallback.expectCallback(CallbackRecord.LOST, mWiFiNetworkAgent);
+        callback.expectCallback(CallbackEntry.LOST, mWiFiNetworkAgent);
+        defaultCallback.expectCallback(CallbackEntry.LOST, mWiFiNetworkAgent);
         defaultCallback.expectAvailableCallbacksValidated(mCellNetworkAgent);
         assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
 
@@ -1813,12 +1820,12 @@
         callback.assertNoCallback();
         // Now unregister cellRequest and expect cell to start lingering.
         mCm.unregisterNetworkCallback(noopCallback);
-        callback.expectCallback(CallbackRecord.LOSING, mCellNetworkAgent);
+        callback.expectCallback(CallbackEntry.LOSING, mCellNetworkAgent);
 
         // Let linger run its course.
         callback.assertNoCallback();
         final int lingerTimeoutMs = mService.mLingerDelayMs + mService.mLingerDelayMs / 4;
-        callback.expectCallback(CallbackRecord.LOST, mCellNetworkAgent, lingerTimeoutMs);
+        callback.expectCallback(CallbackEntry.LOST, mCellNetworkAgent, lingerTimeoutMs);
 
         // Register a TRACK_DEFAULT request and check that it does not affect lingering.
         TestNetworkCallback trackDefaultCallback = new TestNetworkCallback();
@@ -1827,20 +1834,20 @@
         mEthernetNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_ETHERNET);
         mEthernetNetworkAgent.connect(true);
         callback.expectAvailableCallbacksUnvalidated(mEthernetNetworkAgent);
-        callback.expectCallback(CallbackRecord.LOSING, mWiFiNetworkAgent);
+        callback.expectCallback(CallbackEntry.LOSING, mWiFiNetworkAgent);
         callback.expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, mEthernetNetworkAgent);
         trackDefaultCallback.expectAvailableDoubleValidatedCallbacks(mEthernetNetworkAgent);
         defaultCallback.expectAvailableDoubleValidatedCallbacks(mEthernetNetworkAgent);
         assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
 
         // Let linger run its course.
-        callback.expectCallback(CallbackRecord.LOST, mWiFiNetworkAgent, lingerTimeoutMs);
+        callback.expectCallback(CallbackEntry.LOST, mWiFiNetworkAgent, lingerTimeoutMs);
 
         // Clean up.
         mEthernetNetworkAgent.disconnect();
-        callback.expectCallback(CallbackRecord.LOST, mEthernetNetworkAgent);
-        defaultCallback.expectCallback(CallbackRecord.LOST, mEthernetNetworkAgent);
-        trackDefaultCallback.expectCallback(CallbackRecord.LOST, mEthernetNetworkAgent);
+        callback.expectCallback(CallbackEntry.LOST, mEthernetNetworkAgent);
+        defaultCallback.expectCallback(CallbackEntry.LOST, mEthernetNetworkAgent);
+        trackDefaultCallback.expectCallback(CallbackEntry.LOST, mEthernetNetworkAgent);
 
         mCm.unregisterNetworkCallback(callback);
         mCm.unregisterNetworkCallback(defaultCallback);
@@ -1870,7 +1877,7 @@
         mWiFiNetworkAgent.connect(true);
         defaultCallback.expectAvailableDoubleValidatedCallbacks(mWiFiNetworkAgent);
         callback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
-        callback.expectCallback(CallbackRecord.LOSING, mCellNetworkAgent);
+        callback.expectCallback(CallbackEntry.LOSING, mCellNetworkAgent);
         callback.expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, mWiFiNetworkAgent);
 
         // File a request for cellular, then release it.
@@ -1879,7 +1886,7 @@
         NetworkCallback noopCallback = new NetworkCallback();
         mCm.requestNetwork(cellRequest, noopCallback);
         mCm.unregisterNetworkCallback(noopCallback);
-        callback.expectCallback(CallbackRecord.LOSING, mCellNetworkAgent);
+        callback.expectCallback(CallbackEntry.LOSING, mCellNetworkAgent);
 
         // Let linger run its course.
         callback.assertNoCallback();
@@ -1923,12 +1930,12 @@
         // If the user chooses yes on the "No Internet access, stay connected?" dialog, we switch to
         // wifi even though it's unvalidated.
         mCm.setAcceptUnvalidated(mWiFiNetworkAgent.getNetwork(), true, false);
-        callback.expectCallback(CallbackRecord.LOSING, mCellNetworkAgent);
+        callback.expectCallback(CallbackEntry.LOSING, mCellNetworkAgent);
         assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetwork());
 
         // Disconnect wifi, and then reconnect, again with explicitlySelected=true.
         mWiFiNetworkAgent.disconnect();
-        callback.expectCallback(CallbackRecord.LOST, mWiFiNetworkAgent);
+        callback.expectCallback(CallbackEntry.LOST, mWiFiNetworkAgent);
         mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
         mWiFiNetworkAgent.explicitlySelected(true, false);
         mWiFiNetworkAgent.connect(false);
@@ -1937,14 +1944,14 @@
         // If the user chooses no on the "No Internet access, stay connected?" dialog, we ask the
         // network to disconnect.
         mCm.setAcceptUnvalidated(mWiFiNetworkAgent.getNetwork(), false, false);
-        callback.expectCallback(CallbackRecord.LOST, mWiFiNetworkAgent);
+        callback.expectCallback(CallbackEntry.LOST, mWiFiNetworkAgent);
 
         // Reconnect, again with explicitlySelected=true, but this time validate.
         mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
         mWiFiNetworkAgent.explicitlySelected(true, false);
         mWiFiNetworkAgent.connect(true);
         callback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
-        callback.expectCallback(CallbackRecord.LOSING, mCellNetworkAgent);
+        callback.expectCallback(CallbackEntry.LOSING, mCellNetworkAgent);
         callback.expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, mWiFiNetworkAgent);
         assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetwork());
 
@@ -1960,20 +1967,20 @@
         // (i.e., with explicitlySelected=true and acceptUnvalidated=true). Expect to switch to
         // wifi immediately.
         mWiFiNetworkAgent.disconnect();
-        callback.expectCallback(CallbackRecord.LOST, mWiFiNetworkAgent);
+        callback.expectCallback(CallbackEntry.LOST, mWiFiNetworkAgent);
         mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
         mWiFiNetworkAgent.explicitlySelected(true, true);
         mWiFiNetworkAgent.connect(false);
         callback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
-        callback.expectCallback(CallbackRecord.LOSING, mEthernetNetworkAgent);
+        callback.expectCallback(CallbackEntry.LOSING, mEthernetNetworkAgent);
         assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetwork());
         mEthernetNetworkAgent.disconnect();
-        callback.expectCallback(CallbackRecord.LOST, mEthernetNetworkAgent);
+        callback.expectCallback(CallbackEntry.LOST, mEthernetNetworkAgent);
 
         // Disconnect and reconnect with explicitlySelected=false and acceptUnvalidated=true.
         // Check that the network is not scored specially and that the device prefers cell data.
         mWiFiNetworkAgent.disconnect();
-        callback.expectCallback(CallbackRecord.LOST, mWiFiNetworkAgent);
+        callback.expectCallback(CallbackEntry.LOST, mWiFiNetworkAgent);
         mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
         mWiFiNetworkAgent.explicitlySelected(false, true);
         mWiFiNetworkAgent.connect(false);
@@ -1984,8 +1991,8 @@
         mWiFiNetworkAgent.disconnect();
         mCellNetworkAgent.disconnect();
 
-        callback.expectCallback(CallbackRecord.LOST, mWiFiNetworkAgent);
-        callback.expectCallback(CallbackRecord.LOST, mCellNetworkAgent);
+        callback.expectCallback(CallbackEntry.LOST, mWiFiNetworkAgent);
+        callback.expectCallback(CallbackEntry.LOST, mCellNetworkAgent);
     }
 
     private int[] makeIntArray(final int size, final int value) {
@@ -2232,7 +2239,7 @@
         // Need a trigger point to let NetworkMonitor tell ConnectivityService that network is
         // validated.
         mCm.reportNetworkConnectivity(mWiFiNetworkAgent.getNetwork(), true);
-        callback.expectCallback(CallbackRecord.LOSING, mCellNetworkAgent);
+        callback.expectCallback(CallbackEntry.LOSING, mCellNetworkAgent);
         NetworkCapabilities nc = callback.expectCapabilitiesWith(NET_CAPABILITY_VALIDATED,
                 mWiFiNetworkAgent);
         assertTrue(nc.hasCapability(NET_CAPABILITY_PARTIAL_CONNECTIVITY));
@@ -2240,7 +2247,7 @@
 
         // Disconnect and reconnect wifi with partial connectivity again.
         mWiFiNetworkAgent.disconnect();
-        callback.expectCallback(CallbackRecord.LOST, mWiFiNetworkAgent);
+        callback.expectCallback(CallbackEntry.LOST, mWiFiNetworkAgent);
         mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
         mWiFiNetworkAgent.connectWithPartialConnectivity();
         callback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
@@ -2252,7 +2259,7 @@
         // If the user chooses no, disconnect wifi immediately.
         mCm.setAcceptPartialConnectivity(mWiFiNetworkAgent.getNetwork(), false/* accept */,
                 false /* always */);
-        callback.expectCallback(CallbackRecord.LOST, mWiFiNetworkAgent);
+        callback.expectCallback(CallbackEntry.LOST, mWiFiNetworkAgent);
 
         // If user accepted partial connectivity before, and device reconnects to that network
         // again, but now the network has full connectivity. The network shouldn't contain
@@ -2268,14 +2275,14 @@
         // ConnectivityService#updateNetworkInfo().
         callback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
         verify(mWiFiNetworkAgent.mNetworkMonitor, times(1)).setAcceptPartialConnectivity();
-        callback.expectCallback(CallbackRecord.LOSING, mCellNetworkAgent);
+        callback.expectCallback(CallbackEntry.LOSING, mCellNetworkAgent);
         nc = callback.expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, mWiFiNetworkAgent);
         assertFalse(nc.hasCapability(NET_CAPABILITY_PARTIAL_CONNECTIVITY));
 
         // Wifi should be the default network.
         assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetwork());
         mWiFiNetworkAgent.disconnect();
-        callback.expectCallback(CallbackRecord.LOST, mWiFiNetworkAgent);
+        callback.expectCallback(CallbackEntry.LOST, mWiFiNetworkAgent);
 
         // The user accepted partial connectivity and selected "don't ask again". Now the user
         // reconnects to the partial connectivity network. Switch to wifi as soon as partial
@@ -2289,7 +2296,7 @@
         // ConnectivityService#updateNetworkInfo().
         callback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
         verify(mWiFiNetworkAgent.mNetworkMonitor, times(1)).setAcceptPartialConnectivity();
-        callback.expectCallback(CallbackRecord.LOSING, mCellNetworkAgent);
+        callback.expectCallback(CallbackEntry.LOSING, mCellNetworkAgent);
         assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetwork());
         callback.expectCapabilitiesWith(NET_CAPABILITY_PARTIAL_CONNECTIVITY, mWiFiNetworkAgent);
         mWiFiNetworkAgent.setNetworkValid();
@@ -2299,7 +2306,7 @@
         mCm.reportNetworkConnectivity(mWiFiNetworkAgent.getNetwork(), true);
         callback.expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, mWiFiNetworkAgent);
         mWiFiNetworkAgent.disconnect();
-        callback.expectCallback(CallbackRecord.LOST, mWiFiNetworkAgent);
+        callback.expectCallback(CallbackEntry.LOST, mWiFiNetworkAgent);
 
         // If the user accepted partial connectivity, and the device auto-reconnects to the partial
         // connectivity network, it should contain both PARTIAL_CONNECTIVITY and VALIDATED.
@@ -2313,11 +2320,11 @@
         mWiFiNetworkAgent.connectWithPartialValidConnectivity();
         callback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
         verify(mWiFiNetworkAgent.mNetworkMonitor, times(1)).setAcceptPartialConnectivity();
-        callback.expectCallback(CallbackRecord.LOSING, mCellNetworkAgent);
+        callback.expectCallback(CallbackEntry.LOSING, mCellNetworkAgent);
         callback.expectCapabilitiesWith(
                 NET_CAPABILITY_PARTIAL_CONNECTIVITY | NET_CAPABILITY_VALIDATED, mWiFiNetworkAgent);
         mWiFiNetworkAgent.disconnect();
-        callback.expectCallback(CallbackRecord.LOST, mWiFiNetworkAgent);
+        callback.expectCallback(CallbackEntry.LOST, mWiFiNetworkAgent);
     }
 
     @Test
@@ -2359,7 +2366,7 @@
                 false /* always */);
         waitForIdle();
         mCm.reportNetworkConnectivity(mWiFiNetworkAgent.getNetwork(), true);
-        captivePortalCallback.expectCallback(CallbackRecord.LOST, mWiFiNetworkAgent);
+        captivePortalCallback.expectCallback(CallbackEntry.LOST, mWiFiNetworkAgent);
         validatedCallback.expectAvailableCallbacksValidated(mWiFiNetworkAgent);
         NetworkCapabilities nc =
                 validatedCallback.expectCapabilitiesWith(NET_CAPABILITY_PARTIAL_CONNECTIVITY,
@@ -2392,7 +2399,7 @@
         // Take down network.
         // Expect onLost callback.
         mWiFiNetworkAgent.disconnect();
-        captivePortalCallback.expectCallback(CallbackRecord.LOST, mWiFiNetworkAgent);
+        captivePortalCallback.expectCallback(CallbackEntry.LOST, mWiFiNetworkAgent);
 
         // Bring up a network with a captive portal.
         // Expect onAvailable callback of listen for NET_CAPABILITY_CAPTIVE_PORTAL.
@@ -2406,7 +2413,7 @@
         // Expect onLost callback because network no longer provides NET_CAPABILITY_CAPTIVE_PORTAL.
         mWiFiNetworkAgent.setNetworkValid();
         mCm.reportNetworkConnectivity(mWiFiNetworkAgent.getNetwork(), true);
-        captivePortalCallback.expectCallback(CallbackRecord.LOST, mWiFiNetworkAgent);
+        captivePortalCallback.expectCallback(CallbackEntry.LOST, mWiFiNetworkAgent);
 
         // Expect NET_CAPABILITY_VALIDATED onAvailable callback.
         validatedCallback.expectAvailableDoubleValidatedCallbacks(mWiFiNetworkAgent);
@@ -2418,7 +2425,7 @@
         // Expect NET_CAPABILITY_VALIDATED onLost callback.
         mWiFiNetworkAgent.setNetworkInvalid();
         mCm.reportNetworkConnectivity(mWiFiNetworkAgent.getNetwork(), false);
-        validatedCallback.expectCallback(CallbackRecord.LOST, mWiFiNetworkAgent);
+        validatedCallback.expectCallback(CallbackEntry.LOST, mWiFiNetworkAgent);
     }
 
     @Test
@@ -2450,7 +2457,7 @@
         mWiFiNetworkAgent.setNetworkPortal("http://example.com");
         mCm.reportNetworkConnectivity(wifiNetwork, false);
         captivePortalCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
-        validatedCallback.expectCallback(CallbackRecord.LOST, mWiFiNetworkAgent);
+        validatedCallback.expectCallback(CallbackEntry.LOST, mWiFiNetworkAgent);
 
         // Check that startCaptivePortalApp sends the expected command to NetworkMonitor.
         mCm.startCaptivePortalApp(wifiNetwork);
@@ -2471,7 +2478,7 @@
         mWiFiNetworkAgent.setNetworkValid();
         mWiFiNetworkAgent.mNetworkMonitor.forceReevaluation(Process.myUid());
         validatedCallback.expectAvailableCallbacksValidated(mWiFiNetworkAgent);
-        captivePortalCallback.expectCallback(CallbackRecord.LOST, mWiFiNetworkAgent);
+        captivePortalCallback.expectCallback(CallbackEntry.LOST, mWiFiNetworkAgent);
         verify(mNotificationManager, times(1)).notifyAsUser(anyString(),
                 eq(NotificationType.LOGGED_IN.eventId), any(), eq(UserHandle.ALL));
 
@@ -2619,7 +2626,7 @@
         cFoo.assertNoCallback();
 
         mWiFiNetworkAgent.setNetworkSpecifier(nsBar);
-        cFoo.expectCallback(CallbackRecord.LOST, mWiFiNetworkAgent);
+        cFoo.expectCallback(CallbackEntry.LOST, mWiFiNetworkAgent);
         cBar.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
         for (TestNetworkCallback c: emptyCallbacks) {
             c.expectCapabilitiesThat(mWiFiNetworkAgent,
@@ -2647,10 +2654,10 @@
         cBar.assertNoCallback();
 
         mWiFiNetworkAgent.setNetworkSpecifier(null);
-        cFoo.expectCallback(CallbackRecord.LOST, mWiFiNetworkAgent);
-        cBar.expectCallback(CallbackRecord.LOST, mWiFiNetworkAgent);
+        cFoo.expectCallback(CallbackEntry.LOST, mWiFiNetworkAgent);
+        cBar.expectCallback(CallbackEntry.LOST, mWiFiNetworkAgent);
         for (TestNetworkCallback c: emptyCallbacks) {
-            c.expectCallback(CallbackRecord.NETWORK_CAPS_UPDATED, mWiFiNetworkAgent);
+            c.expectCallback(CallbackEntry.NETWORK_CAPS_UPDATED, mWiFiNetworkAgent);
         }
 
         assertNoCallbacks(cEmpty1, cEmpty2, cEmpty3, cEmpty4, cFoo, cBar);
@@ -2793,7 +2800,7 @@
 
         // Bring down cell. Expect no default network callback, since it wasn't the default.
         mCellNetworkAgent.disconnect();
-        cellNetworkCallback.expectCallback(CallbackRecord.LOST, mCellNetworkAgent);
+        cellNetworkCallback.expectCallback(CallbackEntry.LOST, mCellNetworkAgent);
         defaultNetworkCallback.assertNoCallback();
         assertEquals(defaultNetworkCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
 
@@ -2808,11 +2815,11 @@
         // followed by AVAILABLE cell.
         mWiFiNetworkAgent.disconnect();
         cellNetworkCallback.assertNoCallback();
-        defaultNetworkCallback.expectCallback(CallbackRecord.LOST, mWiFiNetworkAgent);
+        defaultNetworkCallback.expectCallback(CallbackEntry.LOST, mWiFiNetworkAgent);
         defaultNetworkCallback.expectAvailableCallbacksValidated(mCellNetworkAgent);
         mCellNetworkAgent.disconnect();
-        cellNetworkCallback.expectCallback(CallbackRecord.LOST, mCellNetworkAgent);
-        defaultNetworkCallback.expectCallback(CallbackRecord.LOST, mCellNetworkAgent);
+        cellNetworkCallback.expectCallback(CallbackEntry.LOST, mCellNetworkAgent);
+        defaultNetworkCallback.expectCallback(CallbackEntry.LOST, mCellNetworkAgent);
         waitForIdle();
         assertEquals(null, mCm.getActiveNetwork());
 
@@ -2829,7 +2836,7 @@
         assertEquals(defaultNetworkCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
 
         vpnNetworkAgent.disconnect();
-        defaultNetworkCallback.expectCallback(CallbackRecord.LOST, vpnNetworkAgent);
+        defaultNetworkCallback.expectCallback(CallbackEntry.LOST, vpnNetworkAgent);
         waitForIdle();
         assertEquals(null, mCm.getActiveNetwork());
     }
@@ -2857,7 +2864,7 @@
         lp.setInterfaceName("foonet_data0");
         mCellNetworkAgent.sendLinkProperties(lp);
         // We should get onLinkPropertiesChanged().
-        cellNetworkCallback.expectCallback(CallbackRecord.LINK_PROPERTIES_CHANGED,
+        cellNetworkCallback.expectCallback(CallbackEntry.LINK_PROPERTIES_CHANGED,
                 mCellNetworkAgent);
         cellNetworkCallback.assertNoCallback();
 
@@ -2865,7 +2872,7 @@
         mCellNetworkAgent.suspend();
         cellNetworkCallback.expectCapabilitiesWithout(NET_CAPABILITY_NOT_SUSPENDED,
                 mCellNetworkAgent);
-        cellNetworkCallback.expectCallback(CallbackRecord.SUSPENDED, mCellNetworkAgent);
+        cellNetworkCallback.expectCallback(CallbackEntry.SUSPENDED, mCellNetworkAgent);
         cellNetworkCallback.assertNoCallback();
 
         // Register a garden variety default network request.
@@ -2880,7 +2887,7 @@
         mCellNetworkAgent.resume();
         cellNetworkCallback.expectCapabilitiesWith(NET_CAPABILITY_NOT_SUSPENDED,
                 mCellNetworkAgent);
-        cellNetworkCallback.expectCallback(CallbackRecord.RESUMED, mCellNetworkAgent);
+        cellNetworkCallback.expectCallback(CallbackEntry.RESUMED, mCellNetworkAgent);
         cellNetworkCallback.assertNoCallback();
 
         dfltNetworkCallback = new TestNetworkCallback();
@@ -2943,10 +2950,10 @@
 
         // When wifi connects, cell lingers.
         callback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
-        callback.expectCallback(CallbackRecord.LOSING, mCellNetworkAgent);
+        callback.expectCallback(CallbackEntry.LOSING, mCellNetworkAgent);
         callback.expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, mWiFiNetworkAgent);
         fgCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
-        fgCallback.expectCallback(CallbackRecord.LOSING, mCellNetworkAgent);
+        fgCallback.expectCallback(CallbackEntry.LOSING, mCellNetworkAgent);
         fgCallback.expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, mWiFiNetworkAgent);
         assertTrue(isForegroundNetwork(mCellNetworkAgent));
         assertTrue(isForegroundNetwork(mWiFiNetworkAgent));
@@ -2954,7 +2961,7 @@
         // When lingering is complete, cell is still there but is now in the background.
         waitForIdle();
         int timeoutMs = TEST_LINGER_DELAY_MS + TEST_LINGER_DELAY_MS / 4;
-        fgCallback.expectCallback(CallbackRecord.LOST, mCellNetworkAgent, timeoutMs);
+        fgCallback.expectCallback(CallbackEntry.LOST, mCellNetworkAgent, timeoutMs);
         // Expect a network capabilities update sans FOREGROUND.
         callback.expectCapabilitiesWithout(NET_CAPABILITY_FOREGROUND, mCellNetworkAgent);
         assertFalse(isForegroundNetwork(mCellNetworkAgent));
@@ -2980,7 +2987,7 @@
         // Release the request. The network immediately goes into the background, since it was not
         // lingering.
         mCm.unregisterNetworkCallback(cellCallback);
-        fgCallback.expectCallback(CallbackRecord.LOST, mCellNetworkAgent);
+        fgCallback.expectCallback(CallbackEntry.LOST, mCellNetworkAgent);
         // Expect a network capabilities update sans FOREGROUND.
         callback.expectCapabilitiesWithout(NET_CAPABILITY_FOREGROUND, mCellNetworkAgent);
         assertFalse(isForegroundNetwork(mCellNetworkAgent));
@@ -2988,8 +2995,8 @@
 
         // Disconnect wifi and check that cell is foreground again.
         mWiFiNetworkAgent.disconnect();
-        callback.expectCallback(CallbackRecord.LOST, mWiFiNetworkAgent);
-        fgCallback.expectCallback(CallbackRecord.LOST, mWiFiNetworkAgent);
+        callback.expectCallback(CallbackEntry.LOST, mWiFiNetworkAgent);
+        fgCallback.expectCallback(CallbackEntry.LOST, mWiFiNetworkAgent);
         fgCallback.expectAvailableCallbacksValidated(mCellNetworkAgent);
         assertTrue(isForegroundNetwork(mCellNetworkAgent));
 
@@ -3126,7 +3133,7 @@
         testFactory.waitForNetworkRequests(1);
 
         // ...  and cell data to be torn down.
-        cellNetworkCallback.expectCallback(CallbackRecord.LOST, mCellNetworkAgent);
+        cellNetworkCallback.expectCallback(CallbackEntry.LOST, mCellNetworkAgent);
         assertLength(1, mCm.getAllNetworks());
 
         testFactory.unregister();
@@ -3215,7 +3222,7 @@
         mWiFiNetworkAgent.setNetworkInvalid();
         mCm.reportNetworkConnectivity(wifiNetwork, false);
         defaultCallback.expectCapabilitiesWithout(NET_CAPABILITY_VALIDATED, mWiFiNetworkAgent);
-        validatedWifiCallback.expectCallback(CallbackRecord.LOST, mWiFiNetworkAgent);
+        validatedWifiCallback.expectCallback(CallbackEntry.LOST, mWiFiNetworkAgent);
 
         // Because avoid bad wifi is off, we don't switch to cellular.
         defaultCallback.assertNoCallback();
@@ -3259,7 +3266,7 @@
         mWiFiNetworkAgent.setNetworkInvalid();
         mCm.reportNetworkConnectivity(wifiNetwork, false);
         defaultCallback.expectCapabilitiesWithout(NET_CAPABILITY_VALIDATED, mWiFiNetworkAgent);
-        validatedWifiCallback.expectCallback(CallbackRecord.LOST, mWiFiNetworkAgent);
+        validatedWifiCallback.expectCallback(CallbackEntry.LOST, mWiFiNetworkAgent);
 
         // Simulate the user selecting "switch" and checking the don't ask again checkbox.
         Settings.Global.putInt(cr, Settings.Global.NETWORK_AVOID_BAD_WIFI, 1);
@@ -3286,7 +3293,7 @@
 
         // If cell goes down, we switch to wifi.
         mCellNetworkAgent.disconnect();
-        defaultCallback.expectCallback(CallbackRecord.LOST, mCellNetworkAgent);
+        defaultCallback.expectCallback(CallbackEntry.LOST, mCellNetworkAgent);
         defaultCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
         validatedWifiCallback.assertNoCallback();
 
@@ -3350,7 +3357,7 @@
         networkCallback.expectAvailableCallbacks(mWiFiNetworkAgent, false, false, false,
                 TEST_CALLBACK_TIMEOUT_MS);
         mWiFiNetworkAgent.disconnect();
-        networkCallback.expectCallback(CallbackRecord.LOST, mWiFiNetworkAgent);
+        networkCallback.expectCallback(CallbackEntry.LOST, mWiFiNetworkAgent);
 
         // Validate that UNAVAILABLE is not called
         networkCallback.assertNoCallback();
@@ -3370,7 +3377,7 @@
         mCm.requestNetwork(nr, networkCallback, timeoutMs);
 
         // pass timeout and validate that UNAVAILABLE is called
-        networkCallback.expectCallback(CallbackRecord.UNAVAILABLE, null);
+        networkCallback.expectCallback(CallbackEntry.UNAVAILABLE, null);
 
         // create a network satisfying request - validate that request not triggered
         mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
@@ -3461,7 +3468,7 @@
             // Simulate the factory releasing the request as unfulfillable and expect onUnavailable!
             testFactory.triggerUnfulfillable(requests.get(newRequestId));
 
-            networkCallback.expectCallback(CallbackRecord.UNAVAILABLE, null);
+            networkCallback.expectCallback(CallbackEntry.UNAVAILABLE, null);
             testFactory.waitForRequests();
 
             // unregister network callback - a no-op (since already freed by the
@@ -4303,7 +4310,7 @@
 
         // Disconnect wifi aware network.
         wifiAware.disconnect();
-        callback.expectCallbackThat(TIMEOUT_MS, (info) -> info instanceof CallbackRecord.Lost);
+        callback.expectCallbackThat(TIMEOUT_MS, (info) -> info instanceof CallbackEntry.Lost);
         mCm.unregisterNetworkCallback(callback);
 
         verifyNoNetwork();
@@ -4352,12 +4359,12 @@
         // ConnectivityService.
         TestNetworkAgentWrapper networkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI, lp);
         networkAgent.connect(true);
-        networkCallback.expectCallback(CallbackRecord.AVAILABLE, networkAgent);
-        networkCallback.expectCallback(CallbackRecord.NETWORK_CAPS_UPDATED, networkAgent);
-        CallbackRecord.LinkPropertiesChanged cbi =
-                networkCallback.expectCallback(CallbackRecord.LINK_PROPERTIES_CHANGED,
+        networkCallback.expectCallback(CallbackEntry.AVAILABLE, networkAgent);
+        networkCallback.expectCallback(CallbackEntry.NETWORK_CAPS_UPDATED, networkAgent);
+        CallbackEntry.LinkPropertiesChanged cbi =
+                networkCallback.expectCallback(CallbackEntry.LINK_PROPERTIES_CHANGED,
                 networkAgent);
-        networkCallback.expectCallback(CallbackRecord.BLOCKED_STATUS, networkAgent);
+        networkCallback.expectCallback(CallbackEntry.BLOCKED_STATUS, networkAgent);
         networkCallback.expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, networkAgent);
         networkCallback.assertNoCallback();
         checkDirectlyConnectedRoutes(cbi.getLp(), Arrays.asList(myIpv4Address),
@@ -4372,7 +4379,7 @@
         newLp.addLinkAddress(myIpv6Address1);
         newLp.addLinkAddress(myIpv6Address2);
         networkAgent.sendLinkProperties(newLp);
-        cbi = networkCallback.expectCallback(CallbackRecord.LINK_PROPERTIES_CHANGED, networkAgent);
+        cbi = networkCallback.expectCallback(CallbackEntry.LINK_PROPERTIES_CHANGED, networkAgent);
         networkCallback.assertNoCallback();
         checkDirectlyConnectedRoutes(cbi.getLp(),
                 Arrays.asList(myIpv4Address, myIpv6Address1, myIpv6Address2),
@@ -4578,12 +4585,12 @@
         assertTrue(ArrayUtils.containsAll(resolvrParams.tlsServers,
                 new String[] { "2001:db8::1", "192.0.2.1" }));
         reset(mMockDnsResolver);
-        cellNetworkCallback.expectCallback(CallbackRecord.AVAILABLE, mCellNetworkAgent);
-        cellNetworkCallback.expectCallback(CallbackRecord.NETWORK_CAPS_UPDATED,
+        cellNetworkCallback.expectCallback(CallbackEntry.AVAILABLE, mCellNetworkAgent);
+        cellNetworkCallback.expectCallback(CallbackEntry.NETWORK_CAPS_UPDATED,
                 mCellNetworkAgent);
-        CallbackRecord.LinkPropertiesChanged cbi = cellNetworkCallback.expectCallback(
-                CallbackRecord.LINK_PROPERTIES_CHANGED, mCellNetworkAgent);
-        cellNetworkCallback.expectCallback(CallbackRecord.BLOCKED_STATUS, mCellNetworkAgent);
+        CallbackEntry.LinkPropertiesChanged cbi = cellNetworkCallback.expectCallback(
+                CallbackEntry.LINK_PROPERTIES_CHANGED, mCellNetworkAgent);
+        cellNetworkCallback.expectCallback(CallbackEntry.BLOCKED_STATUS, mCellNetworkAgent);
         cellNetworkCallback.assertNoCallback();
         assertFalse(cbi.getLp().isPrivateDnsActive());
         assertNull(cbi.getLp().getPrivateDnsServerName());
@@ -4614,7 +4621,7 @@
         setPrivateDnsSettings(PRIVATE_DNS_MODE_PROVIDER_HOSTNAME, "strict.example.com");
         // Can't test dns configuration for strict mode without properly mocking
         // out the DNS lookups, but can test that LinkProperties is updated.
-        cbi = cellNetworkCallback.expectCallback(CallbackRecord.LINK_PROPERTIES_CHANGED,
+        cbi = cellNetworkCallback.expectCallback(CallbackEntry.LINK_PROPERTIES_CHANGED,
                 mCellNetworkAgent);
         cellNetworkCallback.assertNoCallback();
         assertTrue(cbi.getLp().isPrivateDnsActive());
@@ -4637,12 +4644,12 @@
         mCellNetworkAgent.sendLinkProperties(lp);
         mCellNetworkAgent.connect(false);
         waitForIdle();
-        cellNetworkCallback.expectCallback(CallbackRecord.AVAILABLE, mCellNetworkAgent);
-        cellNetworkCallback.expectCallback(CallbackRecord.NETWORK_CAPS_UPDATED,
+        cellNetworkCallback.expectCallback(CallbackEntry.AVAILABLE, mCellNetworkAgent);
+        cellNetworkCallback.expectCallback(CallbackEntry.NETWORK_CAPS_UPDATED,
                 mCellNetworkAgent);
-        CallbackRecord.LinkPropertiesChanged cbi = cellNetworkCallback.expectCallback(
-                CallbackRecord.LINK_PROPERTIES_CHANGED, mCellNetworkAgent);
-        cellNetworkCallback.expectCallback(CallbackRecord.BLOCKED_STATUS, mCellNetworkAgent);
+        CallbackEntry.LinkPropertiesChanged cbi = cellNetworkCallback.expectCallback(
+                CallbackEntry.LINK_PROPERTIES_CHANGED, mCellNetworkAgent);
+        cellNetworkCallback.expectCallback(CallbackEntry.BLOCKED_STATUS, mCellNetworkAgent);
         cellNetworkCallback.assertNoCallback();
         assertFalse(cbi.getLp().isPrivateDnsActive());
         assertNull(cbi.getLp().getPrivateDnsServerName());
@@ -4659,7 +4666,7 @@
         LinkProperties lp2 = new LinkProperties(lp);
         lp2.addDnsServer(InetAddress.getByName("145.100.185.16"));
         mCellNetworkAgent.sendLinkProperties(lp2);
-        cbi = cellNetworkCallback.expectCallback(CallbackRecord.LINK_PROPERTIES_CHANGED,
+        cbi = cellNetworkCallback.expectCallback(CallbackEntry.LINK_PROPERTIES_CHANGED,
                 mCellNetworkAgent);
         cellNetworkCallback.assertNoCallback();
         assertFalse(cbi.getLp().isPrivateDnsActive());
@@ -4683,7 +4690,7 @@
         // private dns fields should be sent.
         mService.mNetdEventCallback.onPrivateDnsValidationEvent(
                 mCellNetworkAgent.getNetwork().netId, "145.100.185.16", "", true);
-        cbi = cellNetworkCallback.expectCallback(CallbackRecord.LINK_PROPERTIES_CHANGED,
+        cbi = cellNetworkCallback.expectCallback(CallbackEntry.LINK_PROPERTIES_CHANGED,
                 mCellNetworkAgent);
         cellNetworkCallback.assertNoCallback();
         assertTrue(cbi.getLp().isPrivateDnsActive());
@@ -4695,7 +4702,7 @@
         LinkProperties lp3 = new LinkProperties(lp2);
         lp3.setMtu(1300);
         mCellNetworkAgent.sendLinkProperties(lp3);
-        cbi = cellNetworkCallback.expectCallback(CallbackRecord.LINK_PROPERTIES_CHANGED,
+        cbi = cellNetworkCallback.expectCallback(CallbackEntry.LINK_PROPERTIES_CHANGED,
                 mCellNetworkAgent);
         cellNetworkCallback.assertNoCallback();
         assertTrue(cbi.getLp().isPrivateDnsActive());
@@ -4708,7 +4715,7 @@
         LinkProperties lp4 = new LinkProperties(lp3);
         lp4.removeDnsServer(InetAddress.getByName("145.100.185.16"));
         mCellNetworkAgent.sendLinkProperties(lp4);
-        cbi = cellNetworkCallback.expectCallback(CallbackRecord.LINK_PROPERTIES_CHANGED,
+        cbi = cellNetworkCallback.expectCallback(CallbackEntry.LINK_PROPERTIES_CHANGED,
                 mCellNetworkAgent);
         cellNetworkCallback.assertNoCallback();
         assertFalse(cbi.getLp().isPrivateDnsActive());
@@ -4799,19 +4806,19 @@
         defaultCallback.expectAvailableCallbacksUnvalidated(vpnNetworkAgent);
         assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
 
-        genericNetworkCallback.expectCallback(CallbackRecord.NETWORK_CAPS_UPDATED, vpnNetworkAgent);
+        genericNetworkCallback.expectCallback(CallbackEntry.NETWORK_CAPS_UPDATED, vpnNetworkAgent);
         genericNotVpnNetworkCallback.assertNoCallback();
         vpnNetworkCallback.expectCapabilitiesThat(vpnNetworkAgent, nc -> null == nc.getUids());
-        defaultCallback.expectCallback(CallbackRecord.NETWORK_CAPS_UPDATED, vpnNetworkAgent);
+        defaultCallback.expectCallback(CallbackEntry.NETWORK_CAPS_UPDATED, vpnNetworkAgent);
         assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
 
         ranges.clear();
         vpnNetworkAgent.setUids(ranges);
 
-        genericNetworkCallback.expectCallback(CallbackRecord.LOST, vpnNetworkAgent);
+        genericNetworkCallback.expectCallback(CallbackEntry.LOST, vpnNetworkAgent);
         genericNotVpnNetworkCallback.assertNoCallback();
         wifiNetworkCallback.assertNoCallback();
-        vpnNetworkCallback.expectCallback(CallbackRecord.LOST, vpnNetworkAgent);
+        vpnNetworkCallback.expectCallback(CallbackEntry.LOST, vpnNetworkAgent);
 
         // TODO : The default network callback should actually get a LOST call here (also see the
         // comment below for AVAILABLE). This is because ConnectivityService does not look at UID
@@ -4819,7 +4826,7 @@
         // can't currently update their UIDs without disconnecting, so this does not matter too
         // much, but that is the reason the test here has to check for an update to the
         // capabilities instead of the expected LOST then AVAILABLE.
-        defaultCallback.expectCallback(CallbackRecord.NETWORK_CAPS_UPDATED, vpnNetworkAgent);
+        defaultCallback.expectCallback(CallbackEntry.NETWORK_CAPS_UPDATED, vpnNetworkAgent);
 
         ranges.add(new UidRange(uid, uid));
         mMockVpn.setUids(ranges);
@@ -4831,23 +4838,23 @@
         vpnNetworkCallback.expectAvailableCallbacksValidated(vpnNetworkAgent);
         // TODO : Here like above, AVAILABLE would be correct, but because this can't actually
         // happen outside of the test, ConnectivityService does not rematch callbacks.
-        defaultCallback.expectCallback(CallbackRecord.NETWORK_CAPS_UPDATED, vpnNetworkAgent);
+        defaultCallback.expectCallback(CallbackEntry.NETWORK_CAPS_UPDATED, vpnNetworkAgent);
 
         mWiFiNetworkAgent.disconnect();
 
-        genericNetworkCallback.expectCallback(CallbackRecord.LOST, mWiFiNetworkAgent);
-        genericNotVpnNetworkCallback.expectCallback(CallbackRecord.LOST, mWiFiNetworkAgent);
-        wifiNetworkCallback.expectCallback(CallbackRecord.LOST, mWiFiNetworkAgent);
+        genericNetworkCallback.expectCallback(CallbackEntry.LOST, mWiFiNetworkAgent);
+        genericNotVpnNetworkCallback.expectCallback(CallbackEntry.LOST, mWiFiNetworkAgent);
+        wifiNetworkCallback.expectCallback(CallbackEntry.LOST, mWiFiNetworkAgent);
         vpnNetworkCallback.assertNoCallback();
         defaultCallback.assertNoCallback();
 
         vpnNetworkAgent.disconnect();
 
-        genericNetworkCallback.expectCallback(CallbackRecord.LOST, vpnNetworkAgent);
+        genericNetworkCallback.expectCallback(CallbackEntry.LOST, vpnNetworkAgent);
         genericNotVpnNetworkCallback.assertNoCallback();
         wifiNetworkCallback.assertNoCallback();
-        vpnNetworkCallback.expectCallback(CallbackRecord.LOST, vpnNetworkAgent);
-        defaultCallback.expectCallback(CallbackRecord.LOST, vpnNetworkAgent);
+        vpnNetworkCallback.expectCallback(CallbackEntry.LOST, vpnNetworkAgent);
+        defaultCallback.expectCallback(CallbackEntry.LOST, vpnNetworkAgent);
         assertEquals(null, mCm.getActiveNetwork());
 
         mCm.unregisterNetworkCallback(genericNetworkCallback);
@@ -4913,7 +4920,7 @@
         assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
 
         vpnNetworkAgent.disconnect();
-        defaultCallback.expectCallback(CallbackRecord.LOST, vpnNetworkAgent);
+        defaultCallback.expectCallback(CallbackEntry.LOST, vpnNetworkAgent);
         defaultCallback.expectAvailableCallbacksValidated(mWiFiNetworkAgent);
 
         mCm.unregisterNetworkCallback(defaultCallback);
@@ -4944,7 +4951,7 @@
         // Even though the VPN is unvalidated, it becomes the default network for our app.
         callback.expectAvailableCallbacksUnvalidated(vpnNetworkAgent);
         // TODO: this looks like a spurious callback.
-        callback.expectCallback(CallbackRecord.NETWORK_CAPS_UPDATED, vpnNetworkAgent);
+        callback.expectCallback(CallbackEntry.NETWORK_CAPS_UPDATED, vpnNetworkAgent);
         callback.assertNoCallback();
 
         assertTrue(vpnNetworkAgent.getScore() > mEthernetNetworkAgent.getScore());
@@ -4969,7 +4976,7 @@
         callback.assertNoCallback();
 
         vpnNetworkAgent.disconnect();
-        callback.expectCallback(CallbackRecord.LOST, vpnNetworkAgent);
+        callback.expectCallback(CallbackEntry.LOST, vpnNetworkAgent);
         callback.expectAvailableCallbacksValidated(mEthernetNetworkAgent);
     }
 
@@ -5411,7 +5418,7 @@
 
         // Switch to METERED network. Restrict the use of the network.
         mWiFiNetworkAgent.disconnect();
-        defaultCallback.expectCallback(CallbackRecord.LOST, mWiFiNetworkAgent);
+        defaultCallback.expectCallback(CallbackEntry.LOST, mWiFiNetworkAgent);
         defaultCallback.expectAvailableCallbacksValidatedAndBlocked(mCellNetworkAgent);
 
         // Network becomes NOT_METERED.
@@ -5425,7 +5432,7 @@
         defaultCallback.assertNoCallback();
 
         mCellNetworkAgent.disconnect();
-        defaultCallback.expectCallback(CallbackRecord.LOST, mCellNetworkAgent);
+        defaultCallback.expectCallback(CallbackEntry.LOST, mCellNetworkAgent);
         defaultCallback.assertNoCallback();
 
         mCm.unregisterNetworkCallback(defaultCallback);
@@ -5501,7 +5508,7 @@
         // the NAT64 prefix was removed because one was never discovered.
         cellLp.addLinkAddress(myIpv4);
         mCellNetworkAgent.sendLinkProperties(cellLp);
-        networkCallback.expectCallback(CallbackRecord.LINK_PROPERTIES_CHANGED, mCellNetworkAgent);
+        networkCallback.expectCallback(CallbackEntry.LINK_PROPERTIES_CHANGED, mCellNetworkAgent);
         verify(mMockDnsResolver, times(1)).stopPrefix64Discovery(cellNetId);
         verify(mMockDnsResolver, atLeastOnce()).setResolverConfiguration(any());
 
@@ -5514,7 +5521,7 @@
         cellLp.removeLinkAddress(myIpv4);
         cellLp.removeRoute(new RouteInfo(myIpv4, null, MOBILE_IFNAME));
         mCellNetworkAgent.sendLinkProperties(cellLp);
-        networkCallback.expectCallback(CallbackRecord.LINK_PROPERTIES_CHANGED, mCellNetworkAgent);
+        networkCallback.expectCallback(CallbackEntry.LINK_PROPERTIES_CHANGED, mCellNetworkAgent);
         verify(mMockDnsResolver, times(1)).startPrefix64Discovery(cellNetId);
 
         // When NAT64 prefix discovery succeeds, LinkProperties are updated and clatd is started.
@@ -5523,14 +5530,14 @@
         mService.mNetdEventCallback.onNat64PrefixEvent(cellNetId, true /* added */,
                 kNat64PrefixString, 96);
         LinkProperties lpBeforeClat = networkCallback.expectCallback(
-                CallbackRecord.LINK_PROPERTIES_CHANGED, mCellNetworkAgent).getLp();
+                CallbackEntry.LINK_PROPERTIES_CHANGED, mCellNetworkAgent).getLp();
         assertEquals(0, lpBeforeClat.getStackedLinks().size());
         assertEquals(kNat64Prefix, lpBeforeClat.getNat64Prefix());
         verify(mMockNetd, times(1)).clatdStart(MOBILE_IFNAME, kNat64Prefix.toString());
 
         // Clat iface comes up. Expect stacked link to be added.
         clat.interfaceLinkStateChanged(CLAT_PREFIX + MOBILE_IFNAME, true);
-        networkCallback.expectCallback(CallbackRecord.LINK_PROPERTIES_CHANGED, mCellNetworkAgent);
+        networkCallback.expectCallback(CallbackEntry.LINK_PROPERTIES_CHANGED, mCellNetworkAgent);
         List<LinkProperties> stackedLps = mCm.getLinkProperties(mCellNetworkAgent.getNetwork())
                 .getStackedLinks();
         assertEquals(makeClatLinkProperties(myIpv4), stackedLps.get(0));
@@ -5538,7 +5545,7 @@
         // Change trivial linkproperties and see if stacked link is preserved.
         cellLp.addDnsServer(InetAddress.getByName("8.8.8.8"));
         mCellNetworkAgent.sendLinkProperties(cellLp);
-        networkCallback.expectCallback(CallbackRecord.LINK_PROPERTIES_CHANGED, mCellNetworkAgent);
+        networkCallback.expectCallback(CallbackEntry.LINK_PROPERTIES_CHANGED, mCellNetworkAgent);
 
         List<LinkProperties> stackedLpsAfterChange =
                 mCm.getLinkProperties(mCellNetworkAgent.getNetwork()).getStackedLinks();
@@ -5556,12 +5563,12 @@
         cellLp.addLinkAddress(myIpv4);
         cellLp.addRoute(new RouteInfo(myIpv4, null, MOBILE_IFNAME));
         mCellNetworkAgent.sendLinkProperties(cellLp);
-        networkCallback.expectCallback(CallbackRecord.LINK_PROPERTIES_CHANGED, mCellNetworkAgent);
+        networkCallback.expectCallback(CallbackEntry.LINK_PROPERTIES_CHANGED, mCellNetworkAgent);
         verify(mMockNetd, times(1)).clatdStop(MOBILE_IFNAME);
         verify(mMockDnsResolver, times(1)).stopPrefix64Discovery(cellNetId);
 
         // As soon as stop is called, the linkproperties lose the stacked interface.
-        networkCallback.expectCallback(CallbackRecord.LINK_PROPERTIES_CHANGED, mCellNetworkAgent);
+        networkCallback.expectCallback(CallbackEntry.LINK_PROPERTIES_CHANGED, mCellNetworkAgent);
         LinkProperties actualLpAfterIpv4 = mCm.getLinkProperties(mCellNetworkAgent.getNetwork());
         LinkProperties expected = new LinkProperties(cellLp);
         expected.setNat64Prefix(kNat64Prefix);
@@ -5588,11 +5595,11 @@
         cellLp.removeRoute(new RouteInfo(myIpv4, null, MOBILE_IFNAME));
         cellLp.removeDnsServer(InetAddress.getByName("8.8.8.8"));
         mCellNetworkAgent.sendLinkProperties(cellLp);
-        networkCallback.expectCallback(CallbackRecord.LINK_PROPERTIES_CHANGED, mCellNetworkAgent);
+        networkCallback.expectCallback(CallbackEntry.LINK_PROPERTIES_CHANGED, mCellNetworkAgent);
         verify(mMockDnsResolver, times(1)).startPrefix64Discovery(cellNetId);
         mService.mNetdEventCallback.onNat64PrefixEvent(cellNetId, true /* added */,
                 kNat64PrefixString, 96);
-        networkCallback.expectCallback(CallbackRecord.LINK_PROPERTIES_CHANGED, mCellNetworkAgent);
+        networkCallback.expectCallback(CallbackEntry.LINK_PROPERTIES_CHANGED, mCellNetworkAgent);
         verify(mMockNetd, times(1)).clatdStart(MOBILE_IFNAME, kNat64Prefix.toString());
 
 
@@ -5612,7 +5619,7 @@
 
         // Clean up.
         mCellNetworkAgent.disconnect();
-        networkCallback.expectCallback(CallbackRecord.LOST, mCellNetworkAgent);
+        networkCallback.expectCallback(CallbackEntry.LOST, mCellNetworkAgent);
         networkCallback.assertNoCallback();
         mCm.unregisterNetworkCallback(networkCallback);
     }
@@ -5644,7 +5651,7 @@
         reset(mNetworkManagementService);
         mWiFiNetworkAgent.connect(true);
         networkCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
-        networkCallback.expectCallback(CallbackRecord.LOSING, mCellNetworkAgent);
+        networkCallback.expectCallback(CallbackEntry.LOSING, mCellNetworkAgent);
         networkCallback.expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, mWiFiNetworkAgent);
         verify(mNetworkManagementService, times(1)).addIdleTimer(eq(WIFI_IFNAME), anyInt(),
                 eq(ConnectivityManager.TYPE_WIFI));
@@ -5653,7 +5660,7 @@
         // Disconnect wifi and switch back to cell
         reset(mNetworkManagementService);
         mWiFiNetworkAgent.disconnect();
-        networkCallback.expectCallback(CallbackRecord.LOST, mWiFiNetworkAgent);
+        networkCallback.expectCallback(CallbackEntry.LOST, mWiFiNetworkAgent);
         assertNoCallbacks(networkCallback);
         verify(mNetworkManagementService, times(1)).removeIdleTimer(eq(WIFI_IFNAME));
         verify(mNetworkManagementService, times(1)).addIdleTimer(eq(MOBILE_IFNAME), anyInt(),
@@ -5665,14 +5672,14 @@
         mWiFiNetworkAgent.sendLinkProperties(wifiLp);
         mWiFiNetworkAgent.connect(true);
         networkCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
-        networkCallback.expectCallback(CallbackRecord.LOSING, mCellNetworkAgent);
+        networkCallback.expectCallback(CallbackEntry.LOSING, mCellNetworkAgent);
         networkCallback.expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, mWiFiNetworkAgent);
 
         // Disconnect cell
         reset(mNetworkManagementService);
         reset(mMockNetd);
         mCellNetworkAgent.disconnect();
-        networkCallback.expectCallback(CallbackRecord.LOST, mCellNetworkAgent);
+        networkCallback.expectCallback(CallbackEntry.LOST, mCellNetworkAgent);
         // LOST callback is triggered earlier than removing idle timer. Broadcast should also be
         // sent as network being switched. Ensure rule removal for cell will not be triggered
         // unexpectedly before network being removed.
@@ -5702,7 +5709,6 @@
     }
 
     @Test
-    @FlakyTest(bugId = 140305678)
     public void testTcpBufferReset() throws Exception {
         final String testTcpBufferSizes = "1,2,3,4,5,6";
         final NetworkRequest networkRequest = new NetworkRequest.Builder()
@@ -5723,12 +5729,12 @@
         LinkProperties lp = new LinkProperties();
         lp.setTcpBufferSizes(testTcpBufferSizes);
         mCellNetworkAgent.sendLinkProperties(lp);
-        networkCallback.expectCallback(CallbackRecord.LINK_PROPERTIES_CHANGED, mCellNetworkAgent);
+        networkCallback.expectCallback(CallbackEntry.LINK_PROPERTIES_CHANGED, mCellNetworkAgent);
         verifyTcpBufferSizeChange(testTcpBufferSizes);
 
         // Clean up.
         mCellNetworkAgent.disconnect();
-        networkCallback.expectCallback(CallbackRecord.LOST, mCellNetworkAgent);
+        networkCallback.expectCallback(CallbackEntry.LOST, mCellNetworkAgent);
         networkCallback.assertNoCallback();
         mCm.unregisterNetworkCallback(networkCallback);
     }
@@ -5947,6 +5953,24 @@
         assertContainsExactly(uidCaptor.getValue(), APP2_UID);
     }
 
+    @Test
+    public void testLinkPropertiesWithWakeOnLanForActiveNetwork() throws Exception {
+        mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
+
+        LinkProperties wifiLp = new LinkProperties();
+        wifiLp.setInterfaceName(WIFI_WOL_IFNAME);
+        wifiLp.setWakeOnLanSupported(false);
+
+        // Default network switch should update ifaces.
+        mWiFiNetworkAgent.connect(false);
+        mWiFiNetworkAgent.sendLinkProperties(wifiLp);
+        waitForIdle();
+
+        // ConnectivityService should have changed the WakeOnLanSupported to true
+        wifiLp.setWakeOnLanSupported(true);
+        assertEquals(wifiLp, mService.getActiveLinkProperties());
+    }
+
 
     private TestNetworkAgentWrapper establishVpn(LinkProperties lp, int establishingUid,
             Set<UidRange> vpnRange) throws Exception {
diff --git a/tests/net/java/com/android/server/connectivity/PermissionMonitorTest.java b/tests/net/java/com/android/server/connectivity/PermissionMonitorTest.java
index 7029218..3fdba6e 100644
--- a/tests/net/java/com/android/server/connectivity/PermissionMonitorTest.java
+++ b/tests/net/java/com/android/server/connectivity/PermissionMonitorTest.java
@@ -54,7 +54,6 @@
 import android.content.Context;
 import android.content.pm.ApplicationInfo;
 import android.content.pm.PackageInfo;
-import android.content.pm.PackageList;
 import android.content.pm.PackageManager;
 import android.content.pm.PackageManagerInternal;
 import android.content.pm.UserInfo;
@@ -70,6 +69,7 @@
 import androidx.test.runner.AndroidJUnit4;
 
 import com.android.server.LocalServices;
+import com.android.server.pm.PackageList;
 
 import org.junit.Before;
 import org.junit.Test;
diff --git a/tools/apilint/apilint.py b/tools/apilint/apilint.py
index 9e42c04..912c1ad 100644
--- a/tools/apilint/apilint.py
+++ b/tools/apilint/apilint.py
@@ -1976,7 +1976,9 @@
     """Catches missing nullability annotations"""
 
     for f in clazz.fields:
-        if f.value is not None and 'static' in f.split and 'final' in f.split:
+        if "enum_constant" in f.split:
+            continue  # Enum constants are never null
+        if f.value is not None and 'final' in f.split:
             continue  # Nullability of constants can be inferred.
         if f.typ not in PRIMITIVES and not has_nullability(f.annotations):
             error(clazz, f, "M12", "Field must be marked either @NonNull or @Nullable")
@@ -1985,8 +1987,12 @@
         verify_nullability_args(clazz, c)
 
     for m in clazz.methods:
-        if m.name == "writeToParcel" or m.name == "onReceive":
-            continue  # Parcelable.writeToParcel() and BroadcastReceiver.onReceive() are not yet annotated
+        if m.name == "writeToParcel" or m.name == "onReceive" or m.name == "onBind":
+            continue  # Parcelable.writeToParcel(), BroadcastReceiver.onReceive(), and Service.onBind() are not yet annotated
+
+        if (m.name == "equals" and m.args == ["java.lang.Object"] or
+                m.name == "toString" and m.args == []):
+            continue  # Nullability of equals and toString is implicit.
 
         if m.typ not in PRIMITIVES and not has_nullability(m.annotations):
             error(clazz, m, "M12", "Return value must be marked either @NonNull or @Nullable")
diff --git a/tools/codegen/src/com/android/codegen/ClassInfo.kt b/tools/codegen/src/com/android/codegen/ClassInfo.kt
index 5061be2..92da9da 100644
--- a/tools/codegen/src/com/android/codegen/ClassInfo.kt
+++ b/tools/codegen/src/com/android/codegen/ClassInfo.kt
@@ -38,6 +38,11 @@
     val superInterfaces = (fileAst.types[0] as ClassOrInterfaceDeclaration)
             .implementedTypes.map { it.asString() }
 
+    val superClass = run {
+        val superClasses = (fileAst.types[0] as ClassOrInterfaceDeclaration).extendedTypes
+        if (superClasses.isNonEmpty) superClasses[0] else null
+    }
+
     val ClassName = classAst.nameAsString
     private val genericArgsAst = classAst.typeParameters
     val genericArgs = if (genericArgsAst.isEmpty()) "" else {
diff --git a/tools/codegen/src/com/android/codegen/ClassPrinter.kt b/tools/codegen/src/com/android/codegen/ClassPrinter.kt
index 1f0d4b8..bd72d9e 100644
--- a/tools/codegen/src/com/android/codegen/ClassPrinter.kt
+++ b/tools/codegen/src/com/android/codegen/ClassPrinter.kt
@@ -1,6 +1,7 @@
 package com.android.codegen
 
 import com.github.javaparser.ast.Modifier
+import com.github.javaparser.ast.body.CallableDeclaration
 import com.github.javaparser.ast.body.ClassOrInterfaceDeclaration
 import com.github.javaparser.ast.body.TypeDeclaration
 import com.github.javaparser.ast.expr.*
@@ -37,6 +38,7 @@
     val GeneratedMember by lazy { classRef("com.android.internal.util.DataClass.Generated.Member") }
     val Parcelling by lazy { classRef("com.android.internal.util.Parcelling") }
     val Parcelable by lazy { classRef("android.os.Parcelable") }
+    val Parcel by lazy { classRef("android.os.Parcel") }
     val UnsupportedAppUsage by lazy { classRef("android.annotation.UnsupportedAppUsage") }
 
     init {
@@ -354,7 +356,9 @@
     }
 
     fun hasMethod(name: String, vararg argTypes: String): Boolean {
-        return classAst.methods.any {
+        val members: List<CallableDeclaration<*>> =
+                if (name == ClassName) classAst.constructors else classAst.methods
+        return members.any {
             it.name.asString() == name &&
                     it.parameters.map { it.type.asString() } == argTypes.toList()
         }
@@ -365,6 +369,10 @@
             .mapIndexed { i, node -> FieldInfo(index = i, fieldAst = node, classInfo = this) }
             .filter { hasMethod("lazyInit${it.NameUpperCamel}") }
 
+    val extendsParcelableClass by lazy {
+        Parcelable !in superInterfaces && superClass != null
+    }
+
     init {
         val builderFactoryOverride = classAst.methods.find {
             it.isStatic && it.nameAsString == "builder"
diff --git a/tools/codegen/src/com/android/codegen/Generators.kt b/tools/codegen/src/com/android/codegen/Generators.kt
index 914e475..5a95676 100644
--- a/tools/codegen/src/com/android/codegen/Generators.kt
+++ b/tools/codegen/src/com/android/codegen/Generators.kt
@@ -341,7 +341,7 @@
             }
         }
 
-        if (Type.contains("Map<")) {
+        if (FieldClass.endsWith("Map") && FieldInnerType != null) {
             generateBuilderMethod(
                     name = adderName,
                     defVisibility = visibility,
@@ -422,6 +422,10 @@
             +"// void parcelFieldName(Parcel dest, int flags) { ... }"
             +""
 
+            if (extendsParcelableClass) {
+                +"super.writeToParcel(dest, flags);\n"
+            }
+
             if (booleanFields.isNotEmpty() || nullableFields.isNotEmpty()) {
                 +"$flagStorageType flg = 0;"
                 booleanFields.forEachApply {
@@ -463,6 +467,123 @@
         +""
     }
 
+    if (!hasMethod(ClassName, Parcel)) {
+        val visibility = if (classAst.isFinal) "/* package-private */" else "protected"
+
+        +"/** @hide */"
+        +"@SuppressWarnings({\"unchecked\", \"RedundantCast\"})"
+        +GENERATED_MEMBER_HEADER
+        "$visibility $ClassName($Parcel in) {" {
+            +"// You can override field unparcelling by defining methods like:"
+            +"// static FieldType unparcelFieldName(Parcel in) { ... }"
+            +""
+
+            if (extendsParcelableClass) {
+                +"super(in);\n"
+            }
+
+            if (booleanFields.isNotEmpty() || nullableFields.isNotEmpty()) {
+                +"$flagStorageType flg = in.read$FlagStorageType();"
+            }
+            booleanFields.forEachApply {
+                +"$Type $_name = (flg & $fieldBit) != 0;"
+            }
+            nonBooleanFields.forEachApply {
+
+                // Handle customized parceling
+                val customParcellingMethod = "unparcel$NameUpperCamel"
+                if (hasMethod(customParcellingMethod, Parcel)) {
+                    +"$Type $_name = $customParcellingMethod(in);"
+                } else if (customParcellingClass != null) {
+                    +"$Type $_name = $sParcelling.unparcel(in);"
+                } else if (hasAnnotation("@$DataClassEnum")) {
+                    val ordinal = "${_name}Ordinal"
+                    +"int $ordinal = in.readInt();"
+                    +"$Type $_name = $ordinal < 0 ? null : $FieldClass.values()[$ordinal];"
+                } else {
+                    val methodArgs = mutableListOf<String>()
+
+                    // Create container if any
+                    val containerInitExpr = when {
+                        FieldClass.endsWith("Map") -> "new $LinkedHashMap<>()"
+                        FieldClass == "List" || FieldClass == "ArrayList" ->
+                            "new ${classRef("java.util.ArrayList")}<>()"
+                        else -> ""
+                    }
+                    val passContainer = containerInitExpr.isNotEmpty()
+
+                    // nullcheck +
+                    // "FieldType fieldName = (FieldType)"
+                    if (passContainer) {
+                        methodArgs.add(_name)
+                        !"$Type $_name = "
+                        if (mayBeNull) {
+                            +"null;"
+                            !"if ((flg & $fieldBit) != 0) {"
+                            pushIndent()
+                            +""
+                            !"$_name = "
+                        }
+                        +"$containerInitExpr;"
+                    } else {
+                        !"$Type $_name = "
+                        if (mayBeNull) !"(flg & $fieldBit) == 0 ? null : "
+                        if (ParcelMethodsSuffix == "StrongInterface") {
+                            !"$FieldClass.Stub.asInterface("
+                        } else if (Type !in PRIMITIVE_TYPES + "String" + "Bundle" &&
+                                (!isArray || FieldInnerType !in PRIMITIVE_TYPES + "String") &&
+                                ParcelMethodsSuffix != "Parcelable") {
+                            !"($FieldClass) "
+                        }
+                    }
+
+                    // Determine method args
+                    when {
+                        ParcelMethodsSuffix == "Parcelable" ->
+                            methodArgs += "$FieldClass.class.getClassLoader()"
+                        ParcelMethodsSuffix == "SparseArray" ->
+                            methodArgs += "$FieldInnerClass.class.getClassLoader()"
+                        ParcelMethodsSuffix == "TypedObject" ->
+                            methodArgs += "$FieldClass.CREATOR"
+                        ParcelMethodsSuffix == "TypedArray" ->
+                            methodArgs += "$FieldInnerClass.CREATOR"
+                        ParcelMethodsSuffix == "Map" ->
+                            methodArgs += "${fieldTypeGenegicArgs[1].substringBefore("<")}.class.getClassLoader()"
+                        ParcelMethodsSuffix.startsWith("Parcelable")
+                                || (isList || isArray)
+                                && FieldInnerType !in PRIMITIVE_TYPES + "String" ->
+                            methodArgs += "$FieldInnerClass.class.getClassLoader()"
+                    }
+
+                    // ...in.readFieldType(args...);
+                    when {
+                        ParcelMethodsSuffix == "StrongInterface" -> !"in.readStrongBinder"
+                        isArray -> !"in.create$ParcelMethodsSuffix"
+                        else -> !"in.read$ParcelMethodsSuffix"
+                    }
+                    !"(${methodArgs.joinToString(", ")})"
+                    if (ParcelMethodsSuffix == "StrongInterface") !")"
+                    +";"
+
+                    // Cleanup if passContainer
+                    if (passContainer && mayBeNull) {
+                        popIndent()
+                        rmEmptyLine()
+                        +"\n}"
+                    }
+                }
+            }
+
+            +""
+            fields.forEachApply {
+                !"this."
+                generateSetFrom(_name)
+            }
+
+            generateOnConstructedCallback()
+        }
+    }
+
     if (classAst.fields.none { it.variables[0].nameAsString == "CREATOR" }) {
         val Creator = classRef("android.os.Parcelable.Creator")
 
@@ -477,104 +598,8 @@
             }
 
             +"@Override"
-            +"@SuppressWarnings({\"unchecked\", \"RedundantCast\"})"
             "public $ClassName createFromParcel($Parcel in)" {
-                +"// You can override field unparcelling by defining methods like:"
-                +"// static FieldType unparcelFieldName(Parcel in) { ... }"
-                +""
-                if (booleanFields.isNotEmpty() || nullableFields.isNotEmpty()) {
-                    +"$flagStorageType flg = in.read$FlagStorageType();"
-                }
-                booleanFields.forEachApply {
-                    +"$Type $_name = (flg & $fieldBit) != 0;"
-                }
-                nonBooleanFields.forEachApply {
-
-                    // Handle customized parceling
-                    val customParcellingMethod = "unparcel$NameUpperCamel"
-                    if (hasMethod(customParcellingMethod, Parcel)) {
-                        +"$Type $_name = $customParcellingMethod(in);"
-                    } else if (customParcellingClass != null) {
-                        +"$Type $_name = $sParcelling.unparcel(in);"
-                    } else if (hasAnnotation("@$DataClassEnum")) {
-                        val ordinal = "${_name}Ordinal"
-                        +"int $ordinal = in.readInt();"
-                        +"$Type $_name = $ordinal < 0 ? null : $FieldClass.values()[$ordinal];"
-                    } else {
-                        val methodArgs = mutableListOf<String>()
-
-                        // Create container if any
-                        val containerInitExpr = when {
-                            FieldClass.endsWith("Map") -> "new $LinkedHashMap<>()"
-                            FieldClass == "List" || FieldClass == "ArrayList" ->
-                                "new ${classRef("java.util.ArrayList")}<>()"
-                            else -> ""
-                        }
-                        val passContainer = containerInitExpr.isNotEmpty()
-
-                        // nullcheck +
-                        // "FieldType fieldName = (FieldType)"
-                        if (passContainer) {
-                            methodArgs.add(_name)
-                            !"$Type $_name = "
-                            if (mayBeNull) {
-                                +"null;"
-                                !"if ((flg & $fieldBit) != 0) {"
-                                pushIndent()
-                                +""
-                                !"$_name = "
-                            }
-                            +"$containerInitExpr;"
-                        } else {
-                            !"$Type $_name = "
-                            if (mayBeNull) !"(flg & $fieldBit) == 0 ? null : "
-                            if (ParcelMethodsSuffix == "StrongInterface") {
-                                !"$FieldClass.Stub.asInterface("
-                            } else if (Type !in PRIMITIVE_TYPES + "String" + "Bundle" &&
-                                    (!isArray || FieldInnerType !in PRIMITIVE_TYPES + "String") &&
-                                    ParcelMethodsSuffix != "Parcelable") {
-                                !"($Type) "
-                            }
-                        }
-
-                        // Determine method args
-                        when {
-                            ParcelMethodsSuffix == "Parcelable" ->
-                                methodArgs += "$FieldClass.class.getClassLoader()"
-                            ParcelMethodsSuffix == "TypedObject" ->
-                                methodArgs += "$FieldClass.CREATOR"
-                            ParcelMethodsSuffix == "TypedArray" ->
-                                methodArgs += "$FieldInnerClass.CREATOR"
-                            ParcelMethodsSuffix.startsWith("Parcelable")
-                                    || FieldClass == "Map"
-                                    || (isList || isArray)
-                                    && FieldInnerType !in PRIMITIVE_TYPES + "String" ->
-                                methodArgs += "$FieldInnerClass.class.getClassLoader()"
-                        }
-
-                        // ...in.readFieldType(args...);
-                        when {
-                            ParcelMethodsSuffix == "StrongInterface" -> !"in.readStrongBinder"
-                            isArray -> !"in.create$ParcelMethodsSuffix"
-                            else -> !"in.read$ParcelMethodsSuffix"
-                        }
-                        !"(${methodArgs.joinToString(", ")})"
-                        if (ParcelMethodsSuffix == "StrongInterface") !")"
-                        +";"
-
-                        // Cleanup if passContainer
-                        if (passContainer && mayBeNull) {
-                            popIndent()
-                            rmEmptyLine()
-                            +"\n}"
-                        }
-                    }
-                }
-                "return new $ClassType(" {
-                    fields.forEachTrimmingTrailingComma {
-                        +"$_name,"
-                    }
-                } + ";"
+                +"return new $ClassName(in);"
             }
             rmEmptyLine()
         } + ";"
diff --git a/tools/codegen/src/com/android/codegen/Main.kt b/tools/codegen/src/com/android/codegen/Main.kt
index 5804674..039f7b2 100755
--- a/tools/codegen/src/com/android/codegen/Main.kt
+++ b/tools/codegen/src/com/android/codegen/Main.kt
@@ -95,7 +95,13 @@
       you can use with final fields.
 
 Version: $CODEGEN_VERSION
-Questions? Feedback? Contact: eugenesusla@
+
+Questions? Feedback?
+Contact: eugenesusla@
+Bug/feature request: http://go/codegen-bug
+
+Slides: http://go/android-codegen
+In-depth example: http://go/SampleDataClass
 """
 
 fun main(args: Array<String>) {
@@ -146,8 +152,7 @@
             generateConstructor("public")
         } else if (FeatureFlag.BUILDER()
                 || FeatureFlag.COPY_CONSTRUCTOR()
-                || FeatureFlag.WITHERS()
-                || FeatureFlag.PARCELABLE()) {
+                || FeatureFlag.WITHERS()) {
             generateConstructor("/* package-private */")
         }
         if (FeatureFlag.COPY_CONSTRUCTOR()) generateCopyConstructor()
diff --git a/tools/codegen/src/com/android/codegen/SharedConstants.kt b/tools/codegen/src/com/android/codegen/SharedConstants.kt
index 1e3973e..47f774f 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.3"
+const val CODEGEN_VERSION = "1.0.7"
 
 const val CANONICAL_BUILDER_CLASS = "Builder"
 const val BASE_BUILDER_CLASS = "BaseBuilder"
diff --git a/tools/processors/staledataclass/src/android/processor/staledataclass/StaleDataclassProcessor.kt b/tools/processors/staledataclass/src/android/processor/staledataclass/StaleDataclassProcessor.kt
index d00def6..7fe21c7 100644
--- a/tools/processors/staledataclass/src/android/processor/staledataclass/StaleDataclassProcessor.kt
+++ b/tools/processors/staledataclass/src/android/processor/staledataclass/StaleDataclassProcessor.kt
@@ -182,6 +182,11 @@
                 .filterNot {
                     it.kind == ElementKind.CLASS
                             || it.kind == ElementKind.CONSTRUCTOR
+                            || it.kind == ElementKind.INTERFACE
+                            || it.kind == ElementKind.ENUM
+                            || it.kind == ElementKind.ANNOTATION_TYPE
+                            || it.kind == ElementKind.INSTANCE_INIT
+                            || it.kind == ElementKind.STATIC_INIT
                             || isGenerated(it)
                 }.map {
                     elemToString(it)
diff --git a/tools/protologtool/src/com/android/protolog/tool/ProtoLogTool.kt b/tools/protologtool/src/com/android/protolog/tool/ProtoLogTool.kt
index 97f3de2..70ac0be 100644
--- a/tools/protologtool/src/com/android/protolog/tool/ProtoLogTool.kt
+++ b/tools/protologtool/src/com/android/protolog/tool/ProtoLogTool.kt
@@ -50,14 +50,19 @@
         command.javaSourceArgs.forEach { path ->
             val file = File(path)
             val text = file.readText()
-            val code = tryParse(text, path)
-            val pack = if (code.packageDeclaration.isPresent) code.packageDeclaration
-                    .get().nameAsString else ""
-            val newPath = pack.replace('.', '/') + '/' + file.name
-            val outSrc = when {
-                containsProtoLogText(text, command.protoLogClassNameArg) ->
+            val newPath = path
+            val outSrc = try {
+                val code = tryParse(text, path)
+                if (containsProtoLogText(text, command.protoLogClassNameArg)) {
                     transformer.processClass(text, newPath, code)
-                else -> text
+                } 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
             }
             outJar.putNextEntry(ZipEntry(newPath))
             outJar.write(outSrc.toByteArray())
@@ -91,11 +96,17 @@
             val file = File(path)
             val text = file.readText()
             if (containsProtoLogText(text, command.protoLogClassNameArg)) {
-                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)
+                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 out = FileOutputStream(command.viewerConfigJsonArg)
diff --git a/wifi/java/android/net/wifi/WifiManager.java b/wifi/java/android/net/wifi/WifiManager.java
index 5782f5b..5496e83 100644
--- a/wifi/java/android/net/wifi/WifiManager.java
+++ b/wifi/java/android/net/wifi/WifiManager.java
@@ -1813,12 +1813,13 @@
     }
 
     /**
-     * Remove the Passpoint configuration identified by its FQDN (Fully Qualified Domain Name).
+     * Remove the Passpoint configuration identified by its FQDN (Fully Qualified Domain Name) added
+     * by the caller.
      *
-     * @param fqdn The FQDN of the Passpoint configuration to be removed
+     * @param fqdn The FQDN of the Passpoint configuration added by the caller to be removed
      * @throws IllegalArgumentException if no configuration is associated with the given FQDN or
      *                                  Passpoint is not enabled on the device.
-     * @deprecated This is no longer supported.
+     * @deprecated This will be non-functional in a future release.
      */
     @Deprecated
     @RequiresPermission(anyOf = {
@@ -1842,12 +1843,12 @@
     }
 
     /**
-     * Return the list of installed Passpoint configurations.
+     * Return the list of installed Passpoint configurations added by the caller.
      *
      * An empty list will be returned when no configurations are installed.
      *
-     * @return A list of {@link PasspointConfiguration}
-     * @deprecated This is no longer supported.
+     * @return A list of {@link PasspointConfiguration} added by the caller
+     * @deprecated This will be non-functional in a future release.
      */
     @Deprecated
     @RequiresPermission(anyOf = {
diff --git a/wifi/java/com/android/server/wifi/BaseWifiService.java b/wifi/java/com/android/server/wifi/BaseWifiService.java
index 2b055d5..4ca2a16 100644
--- a/wifi/java/com/android/server/wifi/BaseWifiService.java
+++ b/wifi/java/com/android/server/wifi/BaseWifiService.java
@@ -206,11 +206,6 @@
         throw new UnsupportedOperationException();
     }
 
-    /** @removed */
-    public void setCountryCode(String country) {
-        throw new UnsupportedOperationException();
-    }
-
     @Override
     public String getCountryCode() {
         throw new UnsupportedOperationException();
@@ -338,11 +333,6 @@
         throw new UnsupportedOperationException();
     }
 
-    /** @removed */
-    public Messenger getWifiServiceMessenger(String packageName) {
-        throw new UnsupportedOperationException();
-    }
-
     @Override
     public void enableTdls(String remoteIPAddress, boolean enable) {
         throw new UnsupportedOperationException();